ibm_watson 0.1.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 +7 -0
- data/README.md +258 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/ibm_watson.rb +16 -0
- data/lib/ibm_watson/assistant_v1.rb +1997 -0
- data/lib/ibm_watson/detailed_response.rb +21 -0
- data/lib/ibm_watson/discovery_v1.rb +2039 -0
- data/lib/ibm_watson/iam_token_manager.rb +166 -0
- data/lib/ibm_watson/language_translator_v3.rb +411 -0
- data/lib/ibm_watson/natural_language_classifier_v1.rb +309 -0
- data/lib/ibm_watson/natural_language_understanding_v1.rb +297 -0
- data/lib/ibm_watson/personality_insights_v3.rb +260 -0
- data/lib/ibm_watson/speech_to_text_v1.rb +2153 -0
- data/lib/ibm_watson/text_to_speech_v1.rb +716 -0
- data/lib/ibm_watson/tone_analyzer_v3.rb +287 -0
- data/lib/ibm_watson/version.rb +3 -0
- data/lib/ibm_watson/visual_recognition_v3.rb +579 -0
- data/lib/ibm_watson/watson_api_exception.rb +41 -0
- data/lib/ibm_watson/watson_service.rb +180 -0
- data/lib/ibm_watson/websocket/recognize_callback.rb +32 -0
- data/lib/ibm_watson/websocket/speech_to_text_websocket_listener.rb +162 -0
- data/rakefile +45 -0
- data/test/integration/test_assistant_v1.rb +645 -0
- data/test/integration/test_discovery_v1.rb +200 -0
- data/test/integration/test_iam_assistant_v1.rb +707 -0
- data/test/integration/test_language_translator_v3.rb +81 -0
- data/test/integration/test_natural_language_classifier_v1.rb +69 -0
- data/test/integration/test_natural_language_understanding_v1.rb +98 -0
- data/test/integration/test_personality_insights_v3.rb +95 -0
- data/test/integration/test_speech_to_text_v1.rb +187 -0
- data/test/integration/test_text_to_speech_v1.rb +81 -0
- data/test/integration/test_tone_analyzer_v3.rb +72 -0
- data/test/integration/test_visual_recognition_v3.rb +64 -0
- data/test/test_helper.rb +22 -0
- data/test/unit/test_assistant_v1.rb +1598 -0
- data/test/unit/test_discovery_v1.rb +1144 -0
- data/test/unit/test_iam_token_manager.rb +165 -0
- data/test/unit/test_language_translator_v3.rb +461 -0
- data/test/unit/test_natural_language_classifier_v1.rb +187 -0
- data/test/unit/test_natural_language_understanding_v1.rb +132 -0
- data/test/unit/test_personality_insights_v3.rb +172 -0
- data/test/unit/test_speech_to_text_v1.rb +755 -0
- data/test/unit/test_text_to_speech_v1.rb +336 -0
- data/test/unit/test_tone_analyzer_v3.rb +200 -0
- data/test/unit/test_vcap_using_personality_insights.rb +150 -0
- data/test/unit/test_visual_recognition_v3.rb +345 -0
- metadata +302 -0
@@ -0,0 +1,166 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require("http")
|
4
|
+
require("json")
|
5
|
+
require("rbconfig")
|
6
|
+
require_relative("./version.rb")
|
7
|
+
|
8
|
+
DEFAULT_IAM_URL = "https://iam.bluemix.net/identity/token".freeze
|
9
|
+
CONTENT_TYPE = "application/x-www-form-urlencoded".freeze
|
10
|
+
ACCEPT = "application/json".freeze
|
11
|
+
DEFAULT_AUTHORIZATION = "Basic Yng6Yng=".freeze
|
12
|
+
REQUEST_TOKEN_GRANT_TYPE = "urn:ibm:params:oauth:grant-type:apikey".freeze
|
13
|
+
REQUEST_TOKEN_RESPONSE_TYPE = "cloud_iam".freeze
|
14
|
+
REFRESH_TOKEN_GRANT_TYPE = "refresh_token".freeze
|
15
|
+
|
16
|
+
# Class to manage IAM Token Authentication
|
17
|
+
class IAMTokenManager
|
18
|
+
attr_accessor :token_info, :user_access_token
|
19
|
+
def initialize(iam_api_key: nil, iam_access_token: nil, iam_url: nil)
|
20
|
+
@iam_api_key = iam_api_key
|
21
|
+
@user_access_token = iam_access_token
|
22
|
+
@iam_url = iam_url.nil? ? DEFAULT_IAM_URL : iam_url
|
23
|
+
@token_info = {
|
24
|
+
"access_token" => nil,
|
25
|
+
"refresh_token" => nil,
|
26
|
+
"token_type" => nil,
|
27
|
+
"expires_in" => nil,
|
28
|
+
"expiration" => nil
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
def request(method:, url:, headers: nil, params: nil, data: nil)
|
33
|
+
user_agent_string = "watson-apis-ruby-sdk-" + IBMWatson::VERSION
|
34
|
+
user_agent_string += " #{RbConfig::CONFIG["host"]}"
|
35
|
+
user_agent_string += " #{RbConfig::CONFIG["RUBY_BASE_NAME"]}-#{RbConfig::CONFIG["RUBY_PROGRAM_VERSION"]}"
|
36
|
+
headers["User-Agent"] = user_agent_string
|
37
|
+
response = nil
|
38
|
+
if headers.key?("Content-Type") && headers["Content-Type"] == CONTENT_TYPE
|
39
|
+
response = HTTP.request(
|
40
|
+
method,
|
41
|
+
url,
|
42
|
+
body: HTTP::URI.form_encode(data),
|
43
|
+
headers: headers,
|
44
|
+
params: params
|
45
|
+
)
|
46
|
+
else
|
47
|
+
data = data.to_json if data.respond_to?(:to_json)
|
48
|
+
response = HTTP.request(
|
49
|
+
method,
|
50
|
+
url,
|
51
|
+
headers: headers,
|
52
|
+
body: data,
|
53
|
+
params: params
|
54
|
+
)
|
55
|
+
end
|
56
|
+
return JSON.parse(response.body.to_s) if (200..299).cover?(response.code)
|
57
|
+
require_relative("./watson_api_exception.rb")
|
58
|
+
raise WatsonApiException.new(response: response)
|
59
|
+
end
|
60
|
+
|
61
|
+
# The source of the token is determined by the following logic:
|
62
|
+
# 1. If user provides their own managed access token, assume it is valid and send it
|
63
|
+
# 2. If this class is managing tokens and does not yet have one, make a request for one
|
64
|
+
# 3. If this class is managing tokens and the token has expired refresh it. In case the refresh token is expired, get a new one
|
65
|
+
# If this class is managing tokens and has a valid token stored, send it
|
66
|
+
def _token
|
67
|
+
return @user_access_token unless @user_access_token.nil? || (@user_access_token.respond_to?(:empty?) && @user_access_token.empty?)
|
68
|
+
if @token_info.all? { |_k, v| v.nil? }
|
69
|
+
token_info = _request_token
|
70
|
+
_save_token_info(
|
71
|
+
token_info: token_info
|
72
|
+
)
|
73
|
+
return @token_info["access_token"]
|
74
|
+
elsif _is_token_expired?
|
75
|
+
token_info = _is_refresh_token_expired? ? _request_token : _refresh_token
|
76
|
+
_save_token_info(
|
77
|
+
token_info: token_info
|
78
|
+
)
|
79
|
+
return @token_info["access_token"]
|
80
|
+
else
|
81
|
+
@token_info["access_token"]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Request an IAM token using an API key
|
86
|
+
def _request_token
|
87
|
+
headers = {
|
88
|
+
"Content-Type" => CONTENT_TYPE,
|
89
|
+
"Authorization" => DEFAULT_AUTHORIZATION,
|
90
|
+
"Accept" => ACCEPT
|
91
|
+
}
|
92
|
+
data = {
|
93
|
+
"grant_type" => REQUEST_TOKEN_GRANT_TYPE,
|
94
|
+
"apikey" => @iam_api_key,
|
95
|
+
"response_type" => REQUEST_TOKEN_RESPONSE_TYPE
|
96
|
+
}
|
97
|
+
response = request(
|
98
|
+
method: "POST",
|
99
|
+
url: @iam_url,
|
100
|
+
headers: headers,
|
101
|
+
data: data
|
102
|
+
)
|
103
|
+
response
|
104
|
+
end
|
105
|
+
|
106
|
+
# Refresh an IAM token using a refresh token
|
107
|
+
def _refresh_token
|
108
|
+
headers = {
|
109
|
+
"Content-Type" => CONTENT_TYPE,
|
110
|
+
"Authorization" => DEFAULT_AUTHORIZATION,
|
111
|
+
"accept" => ACCEPT
|
112
|
+
}
|
113
|
+
data = {
|
114
|
+
"grant_type" => REFRESH_TOKEN_GRANT_TYPE,
|
115
|
+
"refresh_token" => @token_info["refresh_token"]
|
116
|
+
}
|
117
|
+
response = request(
|
118
|
+
method: "POST",
|
119
|
+
url: @iam_url,
|
120
|
+
headers: headers,
|
121
|
+
data: data
|
122
|
+
)
|
123
|
+
response
|
124
|
+
end
|
125
|
+
|
126
|
+
# Set a self-managed IAM access token.
|
127
|
+
# The access token should be valid and not yet expired.
|
128
|
+
def _access_token(iam_access_token:)
|
129
|
+
@user_access_token = iam_access_token
|
130
|
+
end
|
131
|
+
|
132
|
+
# Set the IAM api key
|
133
|
+
def _iam_api_key(iam_api_key:)
|
134
|
+
@iam_api_key = iam_api_key
|
135
|
+
end
|
136
|
+
|
137
|
+
# Check if currently stored token is expired.
|
138
|
+
# Using a buffer to prevent the edge case of the
|
139
|
+
# token expiring before the request could be made.
|
140
|
+
# The buffer will be a fraction of the total TTL. Using 80%.
|
141
|
+
def _is_token_expired?
|
142
|
+
return true if @token_info["expiration"].nil? || @token_info["expires_in"].nil?
|
143
|
+
fraction_of_ttl = 0.8
|
144
|
+
time_to_live = @token_info["expires_in"].nil? ? 0 : @token_info["expires_in"]
|
145
|
+
expire_time = @token_info["expiration"].nil? ? 0 : @token_info["expiration"]
|
146
|
+
refresh_time = expire_time - (time_to_live * (1.0 - fraction_of_ttl))
|
147
|
+
current_time = Time.now.to_i
|
148
|
+
refresh_time < current_time
|
149
|
+
end
|
150
|
+
|
151
|
+
# Used as a fail-safe to prevent the condition of a refresh token expiring,
|
152
|
+
# which could happen after around 30 days. This function will return true
|
153
|
+
# if it has been at least 7 days and 1 hour since the last token was set
|
154
|
+
def _is_refresh_token_expired?
|
155
|
+
return true if @token_info["expiration"].nil?
|
156
|
+
seven_days = 7 * 24 * 3600
|
157
|
+
current_time = Time.now.to_i
|
158
|
+
new_token_time = @token_info["expiration"] + seven_days
|
159
|
+
new_token_time < current_time
|
160
|
+
end
|
161
|
+
|
162
|
+
# Save the response from the IAM service request to the object's state
|
163
|
+
def _save_token_info(token_info:)
|
164
|
+
@token_info = token_info
|
165
|
+
end
|
166
|
+
end
|
@@ -0,0 +1,411 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2018 IBM All Rights Reserved.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
# IBM Watson™ Language Translator translates text from one language to another.
|
18
|
+
# The service offers multiple IBM provided translation models that you can customize based
|
19
|
+
# on your unique terminology and language. Use Language Translator to take news from
|
20
|
+
# across the globe and present it in your language, communicate with your customers in
|
21
|
+
# their own language, and more.
|
22
|
+
|
23
|
+
require "concurrent"
|
24
|
+
require "erb"
|
25
|
+
require "json"
|
26
|
+
require_relative "./detailed_response"
|
27
|
+
|
28
|
+
require_relative "./watson_service"
|
29
|
+
|
30
|
+
module IBMWatson
|
31
|
+
##
|
32
|
+
# The Language Translator V3 service.
|
33
|
+
class LanguageTranslatorV3
|
34
|
+
include Concurrent::Async
|
35
|
+
##
|
36
|
+
# @!method initialize(args)
|
37
|
+
# Construct a new client for the Language Translator service.
|
38
|
+
#
|
39
|
+
# @param args [Hash] The args to initialize with
|
40
|
+
# @option args version [String] The API version date to use with the service, in
|
41
|
+
# "YYYY-MM-DD" format. Whenever the API is changed in a backwards
|
42
|
+
# incompatible way, a new minor version of the API is released.
|
43
|
+
# The service uses the API version for the date you specify, or
|
44
|
+
# the most recent version before that date. Note that you should
|
45
|
+
# not programmatically specify the current date at runtime, in
|
46
|
+
# case the API has been updated since your application's release.
|
47
|
+
# Instead, specify a version date that is compatible with your
|
48
|
+
# application, and don't change it until your application is
|
49
|
+
# ready for a later version.
|
50
|
+
# @option args url [String] The base url to use when contacting the service (e.g.
|
51
|
+
# "https://gateway.watsonplatform.net/language-translator/api").
|
52
|
+
# The base url may differ between Bluemix regions.
|
53
|
+
# @option args username [String] The username used to authenticate with the service.
|
54
|
+
# Username and password credentials are only required to run your
|
55
|
+
# application locally or outside of Bluemix. When running on
|
56
|
+
# Bluemix, the credentials will be automatically loaded from the
|
57
|
+
# `VCAP_SERVICES` environment variable.
|
58
|
+
# @option args password [String] The password used to authenticate with the service.
|
59
|
+
# Username and password credentials are only required to run your
|
60
|
+
# application locally or outside of Bluemix. When running on
|
61
|
+
# Bluemix, the credentials will be automatically loaded from the
|
62
|
+
# `VCAP_SERVICES` environment variable.
|
63
|
+
# @option args iam_api_key [String] An API key that can be used to request IAM tokens. If
|
64
|
+
# this API key is provided, the SDK will manage the token and handle the
|
65
|
+
# refreshing.
|
66
|
+
# @option args iam_access_token [String] An IAM access token is fully managed by the application.
|
67
|
+
# Responsibility falls on the application to refresh the token, either before
|
68
|
+
# it expires or reactively upon receiving a 401 from the service as any requests
|
69
|
+
# made with an expired token will fail.
|
70
|
+
# @option args iam_url [String] An optional URL for the IAM service API. Defaults to
|
71
|
+
# 'https://iam.ng.bluemix.net/identity/token'.
|
72
|
+
def initialize(args = {})
|
73
|
+
@__async_initialized__ = false
|
74
|
+
super()
|
75
|
+
defaults = {}
|
76
|
+
defaults[:version] = nil
|
77
|
+
defaults[:url] = "https://gateway.watsonplatform.net/language-translator/api"
|
78
|
+
defaults[:username] = nil
|
79
|
+
defaults[:password] = nil
|
80
|
+
defaults[:iam_api_key] = nil
|
81
|
+
defaults[:iam_access_token] = nil
|
82
|
+
defaults[:iam_url] = nil
|
83
|
+
args = defaults.merge(args)
|
84
|
+
@watson_service = WatsonService.new(
|
85
|
+
vcap_services_name: "language_translator",
|
86
|
+
url: args[:url],
|
87
|
+
username: args[:username],
|
88
|
+
password: args[:password],
|
89
|
+
iam_api_key: args[:iam_api_key],
|
90
|
+
iam_access_token: args[:iam_access_token],
|
91
|
+
iam_url: args[:iam_url],
|
92
|
+
use_vcap_services: true
|
93
|
+
)
|
94
|
+
@version = args[:version]
|
95
|
+
end
|
96
|
+
|
97
|
+
# :nocov:
|
98
|
+
def add_default_headers(headers: {})
|
99
|
+
@watson_service.add_default_headers(headers: headers)
|
100
|
+
end
|
101
|
+
|
102
|
+
def _iam_access_token(iam_access_token:)
|
103
|
+
@watson_service._iam_access_token(iam_access_token: iam_access_token)
|
104
|
+
end
|
105
|
+
|
106
|
+
def _iam_api_key(iam_api_key:)
|
107
|
+
@watson_service._iam_api_key(iam_api_key: iam_api_key)
|
108
|
+
end
|
109
|
+
|
110
|
+
# @return [DetailedResponse]
|
111
|
+
def request(args)
|
112
|
+
@watson_service.request(args)
|
113
|
+
end
|
114
|
+
|
115
|
+
# @note Chainable
|
116
|
+
# @param headers [Hash] Custom headers to be sent with the request
|
117
|
+
# @return [self]
|
118
|
+
def headers(headers)
|
119
|
+
@watson_service.headers(headers)
|
120
|
+
self
|
121
|
+
end
|
122
|
+
|
123
|
+
def password=(password)
|
124
|
+
@watson_service.password = password
|
125
|
+
end
|
126
|
+
|
127
|
+
def password
|
128
|
+
@watson_service.password
|
129
|
+
end
|
130
|
+
|
131
|
+
def username=(username)
|
132
|
+
@watson_service.username = username
|
133
|
+
end
|
134
|
+
|
135
|
+
def username
|
136
|
+
@watson_service.username
|
137
|
+
end
|
138
|
+
|
139
|
+
def url=(url)
|
140
|
+
@watson_service.url = url
|
141
|
+
end
|
142
|
+
|
143
|
+
def url
|
144
|
+
@watson_service.url
|
145
|
+
end
|
146
|
+
# :nocov:
|
147
|
+
#########################
|
148
|
+
# Translation
|
149
|
+
#########################
|
150
|
+
|
151
|
+
##
|
152
|
+
# @!method translate(text:, model_id: nil, source: nil, target: nil)
|
153
|
+
# Translate.
|
154
|
+
# Translates the input text from the source language to the target language.
|
155
|
+
# @param text [Array[String]] Input text in UTF-8 encoding. Multiple entries will result in multiple
|
156
|
+
# translations in the response.
|
157
|
+
# @param model_id [String] Model ID of the translation model to use. If this is specified, the **source** and
|
158
|
+
# **target** parameters will be ignored. The method requires either a model ID or
|
159
|
+
# both the **source** and **target** parameters.
|
160
|
+
# @param source [String] Language code of the source text language. Use with `target` as an alternative way
|
161
|
+
# to select a translation model. When `source` and `target` are set, and a model ID
|
162
|
+
# is not set, the system chooses a default model for the language pair (usually the
|
163
|
+
# model based on the news domain).
|
164
|
+
# @param target [String] Language code of the translation target language. Use with source as an
|
165
|
+
# alternative way to select a translation model.
|
166
|
+
# @return [DetailedResponse] A `DetailedResponse` object representing the response.
|
167
|
+
def translate(text:, model_id: nil, source: nil, target: nil)
|
168
|
+
raise ArgumentError("text must be provided") if text.nil?
|
169
|
+
headers = {
|
170
|
+
}
|
171
|
+
params = {
|
172
|
+
"version" => @version
|
173
|
+
}
|
174
|
+
data = {
|
175
|
+
"text" => text,
|
176
|
+
"model_id" => model_id,
|
177
|
+
"source" => source,
|
178
|
+
"target" => target
|
179
|
+
}
|
180
|
+
method_url = "/v3/translate"
|
181
|
+
response = request(
|
182
|
+
method: "POST",
|
183
|
+
url: method_url,
|
184
|
+
headers: headers,
|
185
|
+
params: params,
|
186
|
+
json: data,
|
187
|
+
accept_json: true
|
188
|
+
)
|
189
|
+
response
|
190
|
+
end
|
191
|
+
#########################
|
192
|
+
# Identification
|
193
|
+
#########################
|
194
|
+
|
195
|
+
##
|
196
|
+
# @!method list_identifiable_languages
|
197
|
+
# List identifiable languages.
|
198
|
+
# Lists the languages that the service can identify. Returns the language code (for
|
199
|
+
# example, `en` for English or `es` for Spanish) and name of each language.
|
200
|
+
# @return [DetailedResponse] A `DetailedResponse` object representing the response.
|
201
|
+
def list_identifiable_languages
|
202
|
+
headers = {
|
203
|
+
}
|
204
|
+
params = {
|
205
|
+
"version" => @version
|
206
|
+
}
|
207
|
+
method_url = "/v3/identifiable_languages"
|
208
|
+
response = request(
|
209
|
+
method: "GET",
|
210
|
+
url: method_url,
|
211
|
+
headers: headers,
|
212
|
+
params: params,
|
213
|
+
accept_json: true
|
214
|
+
)
|
215
|
+
response
|
216
|
+
end
|
217
|
+
|
218
|
+
##
|
219
|
+
# @!method identify(text:)
|
220
|
+
# Identify language.
|
221
|
+
# Identifies the language of the input text.
|
222
|
+
# @param text [String] Input text in UTF-8 format.
|
223
|
+
# @return [DetailedResponse] A `DetailedResponse` object representing the response.
|
224
|
+
def identify(text:)
|
225
|
+
raise ArgumentError("text must be provided") if text.nil?
|
226
|
+
headers = {
|
227
|
+
}
|
228
|
+
params = {
|
229
|
+
"version" => @version
|
230
|
+
}
|
231
|
+
data = text
|
232
|
+
headers["Content-Type"] = "text/plain"
|
233
|
+
method_url = "/v3/identify"
|
234
|
+
response = request(
|
235
|
+
method: "POST",
|
236
|
+
url: method_url,
|
237
|
+
headers: headers,
|
238
|
+
params: params,
|
239
|
+
data: data,
|
240
|
+
accept_json: true
|
241
|
+
)
|
242
|
+
response
|
243
|
+
end
|
244
|
+
#########################
|
245
|
+
# Models
|
246
|
+
#########################
|
247
|
+
|
248
|
+
##
|
249
|
+
# @!method list_models(source: nil, target: nil, default_models: nil)
|
250
|
+
# List models.
|
251
|
+
# Lists available translation models.
|
252
|
+
# @param source [String] Specify a language code to filter results by source language.
|
253
|
+
# @param target [String] Specify a language code to filter results by target language.
|
254
|
+
# @param default_models [Boolean] If the default parameter isn't specified, the service will return all models
|
255
|
+
# (default and non-default) for each language pair. To return only default models,
|
256
|
+
# set this to `true`. To return only non-default models, set this to `false`. There
|
257
|
+
# is exactly one default model per language pair, the IBM provided base model.
|
258
|
+
# @return [DetailedResponse] A `DetailedResponse` object representing the response.
|
259
|
+
def list_models(source: nil, target: nil, default_models: nil)
|
260
|
+
headers = {
|
261
|
+
}
|
262
|
+
params = {
|
263
|
+
"version" => @version,
|
264
|
+
"source" => source,
|
265
|
+
"target" => target,
|
266
|
+
"default" => default_models
|
267
|
+
}
|
268
|
+
method_url = "/v3/models"
|
269
|
+
response = request(
|
270
|
+
method: "GET",
|
271
|
+
url: method_url,
|
272
|
+
headers: headers,
|
273
|
+
params: params,
|
274
|
+
accept_json: true
|
275
|
+
)
|
276
|
+
response
|
277
|
+
end
|
278
|
+
|
279
|
+
##
|
280
|
+
# @!method create_model(base_model_id:, name: nil, forced_glossary: nil, parallel_corpus: nil, forced_glossary_filename: nil, parallel_corpus_filename: nil)
|
281
|
+
# Create model.
|
282
|
+
# Uploads Translation Memory eXchange (TMX) files to customize a translation model.
|
283
|
+
#
|
284
|
+
# You can either customize a model with a forced glossary or with a corpus that
|
285
|
+
# contains parallel sentences. To create a model that is customized with a parallel
|
286
|
+
# corpus <b>and</b> a forced glossary, proceed in two steps: customize with a
|
287
|
+
# parallel corpus first and then customize the resulting model with a glossary.
|
288
|
+
# Depending on the type of customization and the size of the uploaded corpora,
|
289
|
+
# training can range from minutes for a glossary to several hours for a large
|
290
|
+
# parallel corpus. You can upload a single forced glossary file and this file must
|
291
|
+
# be less than <b>10 MB</b>. You can upload multiple parallel corpora tmx files. The
|
292
|
+
# cumulative file size of all uploaded files is limited to <b>250 MB</b>. To
|
293
|
+
# successfully train with a parallel corpus you must have at least <b>5,000 parallel
|
294
|
+
# sentences</b> in your corpus.
|
295
|
+
#
|
296
|
+
# You can have a <b>maxium of 10 custom models per language pair</b>.
|
297
|
+
# @param base_model_id [String] The model ID of the model to use as the base for customization. To see available
|
298
|
+
# models, use the `List models` method. Usually all IBM provided models are
|
299
|
+
# customizable. In addition, all your models that have been created via parallel
|
300
|
+
# corpus customization, can be further customized with a forced glossary.
|
301
|
+
# @param name [String] An optional model name that you can use to identify the model. Valid characters
|
302
|
+
# are letters, numbers, dashes, underscores, spaces and apostrophes. The maximum
|
303
|
+
# length is 32 characters.
|
304
|
+
# @param forced_glossary [File] A TMX file with your customizations. The customizations in the file completely
|
305
|
+
# overwrite the domain translaton data, including high frequency or high confidence
|
306
|
+
# phrase translations. You can upload only one glossary with a file size less than
|
307
|
+
# 10 MB per call. A forced glossary should contain single words or short phrases.
|
308
|
+
# @param parallel_corpus [File] A TMX file with parallel sentences for source and target language. You can upload
|
309
|
+
# multiple parallel_corpus files in one request. All uploaded parallel_corpus files
|
310
|
+
# combined, your parallel corpus must contain at least 5,000 parallel sentences to
|
311
|
+
# train successfully.
|
312
|
+
# @param forced_glossary_filename [String] The filename for forced_glossary.
|
313
|
+
# @param parallel_corpus_filename [String] The filename for parallel_corpus.
|
314
|
+
# @return [DetailedResponse] A `DetailedResponse` object representing the response.
|
315
|
+
def create_model(base_model_id:, name: nil, forced_glossary: nil, parallel_corpus: nil, forced_glossary_filename: nil, parallel_corpus_filename: nil)
|
316
|
+
raise ArgumentError("base_model_id must be provided") if base_model_id.nil?
|
317
|
+
headers = {
|
318
|
+
}
|
319
|
+
params = {
|
320
|
+
"version" => @version,
|
321
|
+
"base_model_id" => base_model_id,
|
322
|
+
"name" => name
|
323
|
+
}
|
324
|
+
unless forced_glossary.nil?
|
325
|
+
mime_type = "application/octet-stream"
|
326
|
+
unless forced_glossary.instance_of?(StringIO) || forced_glossary.instance_of?(File)
|
327
|
+
forced_glossary = forced_glossary.respond_to?(:to_json) ? StringIO.new(forced_glossary.to_json) : StringIO.new(forced_glossary)
|
328
|
+
end
|
329
|
+
if forced_glossary_filename
|
330
|
+
forced_glossary = forced_glossary.instance_of?(StringIO) ? HTTP::FormData::File.new(forced_glossary, content_type: mime_type, filename: forced_glossary_filename) : HTTP::FormData::File.new(forced_glossary.path, content_type: mime_type, filename: forced_glossary_filename)
|
331
|
+
else
|
332
|
+
forced_glossary = forced_glossary.instance_of?(StringIO) ? HTTP::FormData::File.new(forced_glossary, content_type: mime_type) : HTTP::FormData::File.new(forced_glossary.path, content_type: mime_type)
|
333
|
+
end
|
334
|
+
end
|
335
|
+
unless parallel_corpus.nil?
|
336
|
+
mime_type = "application/octet-stream"
|
337
|
+
unless parallel_corpus.instance_of?(StringIO) || parallel_corpus.instance_of?(File)
|
338
|
+
parallel_corpus = parallel_corpus.respond_to?(:to_json) ? StringIO.new(parallel_corpus.to_json) : StringIO.new(parallel_corpus)
|
339
|
+
end
|
340
|
+
if parallel_corpus_filename
|
341
|
+
parallel_corpus = parallel_corpus.instance_of?(StringIO) ? HTTP::FormData::File.new(parallel_corpus, content_type: mime_type, filename: parallel_corpus_filename) : HTTP::FormData::File.new(parallel_corpus.path, content_type: mime_type, filename: parallel_corpus_filename)
|
342
|
+
else
|
343
|
+
parallel_corpus = parallel_corpus.instance_of?(StringIO) ? HTTP::FormData::File.new(parallel_corpus, content_type: mime_type) : HTTP::FormData::File.new(parallel_corpus.path, content_type: mime_type)
|
344
|
+
end
|
345
|
+
end
|
346
|
+
method_url = "/v3/models"
|
347
|
+
response = request(
|
348
|
+
method: "POST",
|
349
|
+
url: method_url,
|
350
|
+
headers: headers,
|
351
|
+
params: params,
|
352
|
+
form: {
|
353
|
+
forced_glossary: forced_glossary,
|
354
|
+
parallel_corpus: parallel_corpus
|
355
|
+
},
|
356
|
+
accept_json: true
|
357
|
+
)
|
358
|
+
response
|
359
|
+
end
|
360
|
+
|
361
|
+
##
|
362
|
+
# @!method delete_model(model_id:)
|
363
|
+
# Delete model.
|
364
|
+
# Deletes a custom translation model.
|
365
|
+
# @param model_id [String] Model ID of the model to delete.
|
366
|
+
# @return [DetailedResponse] A `DetailedResponse` object representing the response.
|
367
|
+
def delete_model(model_id:)
|
368
|
+
raise ArgumentError("model_id must be provided") if model_id.nil?
|
369
|
+
headers = {
|
370
|
+
}
|
371
|
+
params = {
|
372
|
+
"version" => @version
|
373
|
+
}
|
374
|
+
method_url = "/v3/models/%s" % [ERB::Util.url_encode(model_id)]
|
375
|
+
response = request(
|
376
|
+
method: "DELETE",
|
377
|
+
url: method_url,
|
378
|
+
headers: headers,
|
379
|
+
params: params,
|
380
|
+
accept_json: true
|
381
|
+
)
|
382
|
+
response
|
383
|
+
end
|
384
|
+
|
385
|
+
##
|
386
|
+
# @!method get_model(model_id:)
|
387
|
+
# Get model details.
|
388
|
+
# Gets information about a translation model, including training status for custom
|
389
|
+
# models. Use this API call to poll the status of your customization request. A
|
390
|
+
# successfully completed training will have a status of `available`.
|
391
|
+
# @param model_id [String] Model ID of the model to get.
|
392
|
+
# @return [DetailedResponse] A `DetailedResponse` object representing the response.
|
393
|
+
def get_model(model_id:)
|
394
|
+
raise ArgumentError("model_id must be provided") if model_id.nil?
|
395
|
+
headers = {
|
396
|
+
}
|
397
|
+
params = {
|
398
|
+
"version" => @version
|
399
|
+
}
|
400
|
+
method_url = "/v3/models/%s" % [ERB::Util.url_encode(model_id)]
|
401
|
+
response = request(
|
402
|
+
method: "GET",
|
403
|
+
url: method_url,
|
404
|
+
headers: headers,
|
405
|
+
params: params,
|
406
|
+
accept_json: true
|
407
|
+
)
|
408
|
+
response
|
409
|
+
end
|
410
|
+
end
|
411
|
+
end
|