asimov 0.1.0 → 1.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.
@@ -4,28 +4,54 @@ module Asimov
4
4
  # Class interface for API methods in the "/fine-tunes" URI subspace.
5
5
  ##
6
6
  class Finetunes < Base
7
- URI_PREFIX = "/fine-tunes".freeze
7
+ RESOURCE = "fine-tunes".freeze
8
+ private_constant :RESOURCE
8
9
 
10
+ ##
11
+ # Lists the set of fine-tuning jobs for this API key and (optionally) organization.
12
+ ##
9
13
  def list
10
- http_get(path: URI_PREFIX)
14
+ rest_index(resource: RESOURCE)
11
15
  end
12
16
 
13
- def create(parameters:)
14
- raise MissingRequiredParameterError.new(:training_file) unless parameters[:training_file]
17
+ ##
18
+ # Creates a new fine-tuning job with the specified parameters.
19
+ #
20
+ # @param [String] training_file the id of the training file to use for fine tuning
21
+ # @param [Hash] parameters the parameters passed with the fine tuning job
22
+ ##
23
+ def create(training_file:, parameters: {})
24
+ raise MissingRequiredParameterError.new(:training_file) unless training_file
15
25
 
16
- json_post(path: URI_PREFIX, parameters: parameters)
26
+ rest_create_w_json_params(resource: RESOURCE,
27
+ parameters: parameters.merge(training_file: training_file))
17
28
  end
18
29
 
30
+ ##
31
+ # Retrieves the details of a fine-tuning job with the specified id.
32
+ #
33
+ # @param [String] fine_tune_id the id of fine tuning job
34
+ ##
19
35
  def retrieve(fine_tune_id:)
20
- http_get(path: "#{URI_PREFIX}/#{fine_tune_id}")
36
+ rest_get(resource: RESOURCE, id: fine_tune_id)
21
37
  end
22
38
 
39
+ ##
40
+ # Cancels the details of a fine-tuning job with the specified id.
41
+ #
42
+ # @param [String] fine_tune_id the id of fine tuning job
43
+ ##
23
44
  def cancel(fine_tune_id:)
24
- multipart_post(path: "#{URI_PREFIX}/#{fine_tune_id}/cancel")
45
+ rest_create_w_multipart_params(resource: [RESOURCE, fine_tune_id, "cancel"])
25
46
  end
26
47
 
27
- def events(fine_tune_id:)
28
- http_get(path: "#{URI_PREFIX}/#{fine_tune_id}/events")
48
+ ##
49
+ # Lists the events associated with a fine-tuning job with the specified id.
50
+ #
51
+ # @param [String] fine_tune_id the id of fine tuning job
52
+ ##
53
+ def list_events(fine_tune_id:)
54
+ rest_index(resource: [RESOURCE, fine_tune_id, "events"])
29
55
  end
30
56
  end
31
57
  end
@@ -6,22 +6,49 @@ module Asimov
6
6
  # Class interface for API methods in the "/images" URI subspace.
7
7
  ##
8
8
  class Images < Base
9
- URI_PREFIX = "/images".freeze
9
+ RESOURCE = "images".freeze
10
+ private_constant :RESOURCE
10
11
 
11
- def create(parameters:)
12
- raise MissingRequiredParameterError.new(:prompt) unless parameters[:prompt]
12
+ ##
13
+ # Creates an image using the specified prompt.
14
+ #
15
+ # @param [String] prompt the prompt used to create the image
16
+ # @param [Hash] parameters additional parameters passed to the API
17
+ ##
18
+ def create(prompt:, parameters: {})
19
+ raise MissingRequiredParameterError.new(:prompt) unless prompt
13
20
 
14
- json_post(path: "#{URI_PREFIX}/generations", parameters: parameters)
21
+ rest_create_w_json_params(resource: [RESOURCE, "generations"],
22
+ parameters: parameters.merge({ prompt: prompt }))
15
23
  end
16
24
 
17
- def create_edit(parameters:)
18
- raise MissingRequiredParameterError.new(:prompt) unless parameters[:prompt]
25
+ ##
26
+ # Creates edits of the specified image based on the prompt.
27
+ #
28
+ # @param [String] image file name or a File-like object of the base image
29
+ # @param [String] prompt the prompt used to guide the edit
30
+ # @param [Hash] parameters additional parameters passed to the API
31
+ ##
32
+ def create_edit(image:, prompt:, parameters: {})
33
+ raise MissingRequiredParameterError.new(:prompt) unless prompt
19
34
 
20
- multipart_post(path: "#{URI_PREFIX}/edits", parameters: open_files(parameters))
35
+ rest_create_w_multipart_params(resource: [RESOURCE, "edits"],
36
+ parameters: open_files(parameters.merge({
37
+ image: image,
38
+ prompt: prompt
39
+ })))
21
40
  end
22
41
 
23
- def create_variation(parameters:)
24
- multipart_post(path: "#{URI_PREFIX}/variations", parameters: open_files(parameters))
42
+ ##
43
+ # Creates variations of the specified image.
44
+ #
45
+ # @param [String] image file name or a File-like object of the base image
46
+ # @param [Hash] parameters additional parameters passed to the API
47
+ # @option parameters [String] :mask mask file name or a File-like object
48
+ ##
49
+ def create_variation(image:, parameters: {})
50
+ rest_create_w_multipart_params(resource: [RESOURCE, "variations"],
51
+ parameters: open_files(parameters.merge({ image: image })))
25
52
  end
26
53
 
27
54
  private
@@ -30,7 +57,7 @@ module Asimov
30
57
  raise MissingRequiredParameterError.new(:image) unless parameters[:image]
31
58
 
32
59
  parameters = parameters.merge(image: Utils::FileManager.open(parameters[:image]))
33
- parameters.merge!(mask: Utils::FileManager.open(parameters[:mask])) if parameters[:mask]
60
+ parameters[:mask] = Utils::FileManager.open(parameters[:mask]) if parameters[:mask]
34
61
  parameters
35
62
  end
36
63
  end
@@ -4,18 +4,35 @@ module Asimov
4
4
  # Class interface for API methods in the "/models" URI subspace.
5
5
  ##
6
6
  class Models < Base
7
- URI_PREFIX = "/models".freeze
7
+ RESOURCE = "models".freeze
8
+ private_constant :RESOURCE
8
9
 
10
+ ##
11
+ # Lists the models accessible to this combination of OpenAI API
12
+ # key and organization id.
13
+ ##
9
14
  def list
10
- http_get(path: URI_PREFIX)
15
+ rest_index(resource: RESOURCE)
11
16
  end
12
17
 
18
+ ##
19
+ # Retrieve information about the model with the specified
20
+ # model_id.
21
+ #
22
+ # @param [String] model_id the id of the model to be retrieved
23
+ ##
13
24
  def retrieve(model_id:)
14
- http_get(path: "#{URI_PREFIX}/#{model_id}")
25
+ rest_get(resource: RESOURCE, id: model_id)
15
26
  end
16
27
 
28
+ ##
29
+ # Deletes the model with the specified model_id. Only
30
+ # works on models created via fine tuning.
31
+ #
32
+ # @param [String] model_id the id of the model to be deleted
33
+ ##
17
34
  def delete(model_id:)
18
- http_delete(path: "#{URI_PREFIX}/#{model_id}")
35
+ rest_delete(resource: RESOURCE, id: model_id)
19
36
  end
20
37
  end
21
38
  end
@@ -4,10 +4,17 @@ module Asimov
4
4
  # Class interface for API methods in the "/moderations" URI subspace.
5
5
  ##
6
6
  class Moderations < Base
7
- def create(parameters:)
8
- raise MissingRequiredParameterError.new(:input) unless parameters[:input]
7
+ ##
8
+ # Calls the /moderations POST endpoint with the specified parameters.
9
+ #
10
+ # @param [String] input the text being evaluated by the API
11
+ # @param [Hash] parameters the set of parameters being passed to the API
12
+ ##
13
+ def create(input:, parameters: {})
14
+ raise MissingRequiredParameterError.new(:input) unless input
9
15
 
10
- json_post(path: "/moderations", parameters: parameters)
16
+ rest_create_w_json_params(resource: "moderations",
17
+ parameters: parameters.merge({ input: input }))
11
18
  end
12
19
  end
13
20
  end
data/lib/asimov/client.rb CHANGED
@@ -3,6 +3,8 @@ require "httparty"
3
3
  require_relative "headers_factory"
4
4
  require_relative "utils/request_options_validator"
5
5
  require_relative "api_v1/base"
6
+ require_relative "api_v1/audio"
7
+ require_relative "api_v1/chat"
6
8
  require_relative "api_v1/completions"
7
9
  require_relative "api_v1/edits"
8
10
  require_relative "api_v1/embeddings"
@@ -20,7 +22,7 @@ module Asimov
20
22
  class Client
21
23
  extend Forwardable
22
24
 
23
- attr_reader :api_key, :organization_id, :api_version, :request_options
25
+ attr_reader :api_key, :organization_id, :api_version, :request_options, :openai_api_base
24
26
 
25
27
  ##
26
28
  # Creates a new Asimov::Client. Includes several optional named parameters:
@@ -29,17 +31,36 @@ module Asimov
29
31
  # defaults to the application-wide configuration
30
32
  # organization_id - The OpenAI organization identifier that this Asimov::Client instance
31
33
  # will use. If unspecified, defaults to the application-wide configuration.
34
+ # request_options - HTTParty request options that will be passed to the underlying network
35
+ # client. Merges (and overrides) global configuration value.
36
+ # openai_api_base - Custom base URI for the API calls made by this client. Defaults to global
37
+ # configuration value.
32
38
  ##
33
39
  def initialize(api_key: nil, organization_id: HeadersFactory::NULL_ORGANIZATION_ID,
34
- request_options: {})
40
+ request_options: {}, openai_api_base: nil)
35
41
  @headers_factory = HeadersFactory.new(api_key,
36
42
  organization_id)
37
43
  @request_options = Asimov.configuration.request_options
38
44
  .merge(Utils::RequestOptionsValidator.validate(request_options))
39
45
  .freeze
46
+ initialize_openai_api_base(openai_api_base)
40
47
  end
41
48
  def_delegators :@headers_factory, :api_key, :organization_id, :headers
42
49
 
50
+ ##
51
+ # Use the audio method to access API calls in the /audio URI space.
52
+ ##
53
+ def audio
54
+ @audio ||= Asimov::ApiV1::Audio.new(client: self)
55
+ end
56
+
57
+ ##
58
+ # Use the chat method to access API calls in the /chat URI space.
59
+ ##
60
+ def chat
61
+ @chat ||= Asimov::ApiV1::Chat.new(client: self)
62
+ end
63
+
43
64
  ##
44
65
  # Use the completions method to access API calls in the /completions URI space.
45
66
  ##
@@ -95,5 +116,17 @@ module Asimov
95
116
  def moderations
96
117
  @moderations ||= Asimov::ApiV1::Moderations.new(client: self)
97
118
  end
119
+
120
+ private
121
+
122
+ def initialize_openai_api_base(openai_api_base)
123
+ @openai_api_base = openai_api_base || Asimov.configuration.openai_api_base
124
+ if @openai_api_base
125
+ @openai_api_base = HTTParty.normalize_base_uri(@openai_api_base)
126
+ else
127
+ raise Asimov::MissingBaseUriError,
128
+ "No API Base URI was provided for this client."
129
+ end
130
+ end
98
131
  end
99
132
  end
@@ -9,18 +9,39 @@ module Asimov
9
9
  class Configuration
10
10
  attr_accessor :api_key, :organization_id
11
11
 
12
- attr_reader :request_options
12
+ attr_reader :request_options, :openai_api_base
13
13
 
14
+ DEFAULT_OPENAI_BASE_URI = "https://api.openai.com/v1".freeze
15
+
16
+ ##
17
+ # Initializes the Configuration object and resets it to default values.
18
+ ##
14
19
  def initialize
15
20
  reset
16
21
  end
17
22
 
23
+ ##
24
+ # Reset the configuration to default values. Mostly used for testing.
25
+ ##
18
26
  def reset
19
27
  @api_key = nil
20
28
  @organization_id = nil
21
29
  @request_options = {}
30
+ @openai_api_base = DEFAULT_OPENAI_BASE_URI
31
+ end
32
+
33
+ ##
34
+ # Sets the openai_api_base on the Configuration. Typically not invoked
35
+ # directly, but rather through use of `Asimov.configure`.
36
+ ##
37
+ def openai_api_base=(val)
38
+ @openai_api_base = val ? HTTParty.normalize_base_uri(val) : nil
22
39
  end
23
40
 
41
+ ##
42
+ # Sets the request_options on the Configuration. Typically not invoked
43
+ # directly, but rather through use of `Asimov.configure`.
44
+ ##
24
45
  def request_options=(val)
25
46
  @request_options = Utils::RequestOptionsValidator.validate(val)
26
47
  end
data/lib/asimov/error.rb CHANGED
@@ -9,8 +9,18 @@ module Asimov
9
9
  ##
10
10
  class ConfigurationError < Error; end
11
11
 
12
+ ##
13
+ # Error that occurs when there is no configured
14
+ # API key for a newly created Asimov::Client.
15
+ ##
12
16
  class MissingApiKeyError < ConfigurationError; end
13
17
 
18
+ ##
19
+ # Error that occurs when there is no configured
20
+ # base URI for a newly created Asimov::Client.
21
+ ##
22
+ class MissingBaseUriError < ConfigurationError; end
23
+
14
24
  ##
15
25
  # Errors that occur when making an API request. They
16
26
  # can occur either through local validation or
@@ -56,6 +66,18 @@ module Asimov
56
66
  ##
57
67
  class AuthorizationError < RequestError; end
58
68
 
69
+ ##
70
+ # Error that occurs because the provided API key is not
71
+ # valid.
72
+ ##
73
+ class InvalidApiKeyError < AuthorizationError; end
74
+
75
+ ##
76
+ # Error that occurs because the provided API key is not
77
+ # valid.
78
+ ##
79
+ class InvalidOrganizationError < AuthorizationError; end
80
+
59
81
  ##
60
82
  # Errors that occur because of issues with the
61
83
  # parameters of a request. Typically these correspond
@@ -87,26 +109,60 @@ module Asimov
87
109
  @system_message = system_message
88
110
  end
89
111
 
112
+ ##
113
+ # Returns the error message based on the file name and the wrapped error.
114
+ ##
90
115
  def message
91
116
  "The file #{@file_name} could not be opened for upload because of the " \
92
117
  "following error - #{@system_message}."
93
118
  end
94
119
  end
95
120
 
121
+ ##
122
+ # Error that occurs when a JSONL file is expected
123
+ # and it cannot be parsed.
124
+ ##
96
125
  class JsonlFileCannotBeParsedError < FileDataError; end
97
126
 
127
+ ##
128
+ # Error that occurs when an invalid training example
129
+ # is found in a training file.
130
+ ##
98
131
  class InvalidTrainingExampleError < FileDataError; end
99
132
 
133
+ ##
134
+ # Error that occurs when an invalid text entry
135
+ # is found in a text entry file.
136
+ ##
100
137
  class InvalidTextEntryError < FileDataError; end
101
138
 
139
+ ##
140
+ # Error that occurs when an invalid classification
141
+ # is found in a classifications file.
142
+ ##
102
143
  class InvalidClassificationError < FileDataError; end
103
144
 
145
+ ##
146
+ # Error that occurs when the provided chat messages
147
+ # parameter is not valid.
148
+ ##
149
+ class InvalidChatMessagesError < RequestError; end
150
+
151
+ ##
152
+ # Error that occurs when an invalid value is provided
153
+ # for an expected parameter in a request.
154
+ ##
104
155
  class InvalidParameterValueError < RequestError; end
105
156
 
157
+ ##
158
+ # Error that occurs when an unexpected parameter is
159
+ # provided in a request.
160
+ ##
106
161
  class UnsupportedParameterError < RequestError; end
107
162
 
108
163
  ##
109
- #
164
+ # Error raised when a required parameter is not included
165
+ # in the request.
110
166
  ##
111
167
  class MissingRequiredParameterError < RequestError
112
168
  def initialize(parameter_name)
@@ -114,6 +170,9 @@ module Asimov
114
170
  @parameter_name = parameter_name
115
171
  end
116
172
 
173
+ ##
174
+ # Returns the error message based on the missing parameter name.
175
+ ##
117
176
  def message
118
177
  "The parameter #{@parameter_name} is required."
119
178
  end
@@ -126,4 +185,39 @@ module Asimov
126
185
  # an object in the OpenAI system.
127
186
  ##
128
187
  class NotFoundError < RequestError; end
188
+
189
+ ##
190
+ # Errors that occur because the OpenAI API returned
191
+ # an HTTP code 429. This typically occurs because
192
+ # you have hit a rate limit or quota limit, or
193
+ # because the engine is overloaded.
194
+ ##
195
+ class TooManyRequestsError < RequestError; end
196
+
197
+ ##
198
+ # Error that occurs when the quota for an API key
199
+ # is exceeded.
200
+ ##
201
+ class QuotaExceededError < TooManyRequestsError; end
202
+
203
+ ##
204
+ # Error that occurs when the rate limit for requests
205
+ # is exceeded.
206
+ ##
207
+ class RateLimitError < TooManyRequestsError; end
208
+
209
+ ##
210
+ # Error that occurs when the API itself is
211
+ # overloaded and temporarily cannot accept additional
212
+ # requests.
213
+ ##
214
+ class ApiOverloadedError < TooManyRequestsError; end
215
+
216
+ ##
217
+ # Raised when a non-false stream parameter is passed
218
+ # to certain API methods. Processing of server-side
219
+ # events using the stream parameter is currently not
220
+ # supported.
221
+ ##
222
+ class StreamingResponseNotSupportedError < RequestError; end
129
223
  end
@@ -0,0 +1,63 @@
1
+ module Asimov
2
+ module Utils
3
+ ##
4
+ # Validator for OpenAI's chat message format
5
+ ##
6
+ class ChatMessagesValidator
7
+ def self.validate_and_normalize(messages)
8
+ new.validate(messages)
9
+ end
10
+
11
+ def validate(messages)
12
+ raise InvalidChatMessagesError, "Chat messages cannot be nil." if messages.nil?
13
+
14
+ unless messages.is_a?(Array)
15
+ raise InvalidChatMessagesError,
16
+ "Chat messages must be an array."
17
+ end
18
+
19
+ messages.map do |message|
20
+ validate_message(normalize_parsed(message))
21
+ end
22
+ rescue JSON::ParserError
23
+ raise InvalidChatMessagesError, "Chat messages must be valid JSON."
24
+ end
25
+
26
+ def validate_message(message)
27
+ raise InvalidChatMessagesError, "Chat messages must be hashes." unless message.is_a?(Hash)
28
+
29
+ validate_role(message["role"])
30
+
31
+ content = message["content"]
32
+ raise InvalidChatMessagesError, "Chat messages must have content." if content.nil?
33
+
34
+ validate_keys(message)
35
+ message
36
+ end
37
+
38
+ def validate_keys(json)
39
+ additional_keys = json.keys - %w[role content]
40
+ return if additional_keys.empty?
41
+
42
+ raise InvalidChatMessagesError,
43
+ "Chat messages must not have additional keys - #{additional_keys.join(', ')}."
44
+ end
45
+
46
+ ALLOWED_ROLES = %w[assistant system user].freeze
47
+ def validate_role(role)
48
+ raise InvalidChatMessagesError, "Chat messages must have a role." if role.nil?
49
+
50
+ return true if ALLOWED_ROLES.include?(role)
51
+
52
+ raise InvalidChatMessagesError,
53
+ "The value '#{role}' is not a valid role for a chat message."
54
+ end
55
+
56
+ def normalize_parsed(message)
57
+ return message if message.is_a?(String)
58
+
59
+ JSON.parse(message.respond_to?(:to_json) ? message.to_json : message)
60
+ end
61
+ end
62
+ end
63
+ end
@@ -1,6 +1,9 @@
1
1
  require "json"
2
2
 
3
3
  module Asimov
4
+ ##
5
+ # Set of utilities, primarily intended for internal library use.
6
+ ##
4
7
  module Utils
5
8
  ##
6
9
  # Validates that a file is in the "classifications" format
@@ -8,8 +11,13 @@ module Asimov
8
11
  # "text" and "label" keys for each line that have string
9
12
  # values and an optional "metadata" key that can have
10
13
  # any value. No other keys are permitted.
14
+ #
15
+ # The only method that clients should call on instances
16
+ # of this class is `validate`
11
17
  ##
12
18
  class ClassificationsFileValidator < JsonlValidator
19
+ private
20
+
13
21
  def validate_line(line, idx)
14
22
  parsed = JSON.parse(line)
15
23
  validate_classification(parsed, idx)
@@ -8,11 +8,23 @@ module Asimov
8
8
  # Not intended for client use.
9
9
  ##
10
10
  class FileManager
11
- def self.open(filename)
12
- File.open(filename)
11
+ ##
12
+ # Returns the file corresponding to the file_or_path. If the argument is a
13
+ # file, then just returns the argument. Otherwise calls File.open with the
14
+ # argument. Raises an error if the file cannot be opened.
15
+ #
16
+ # @param [File/String] file_or_path the path to the file to be opened
17
+ ##
18
+ def self.open(file_or_path)
19
+ file?(file_or_path) ? file_or_path : File.open(file_or_path)
13
20
  rescue SystemCallError => e
14
- raise Asimov::FileCannotBeOpenedError.new(filename, e.message)
21
+ raise Asimov::FileCannotBeOpenedError.new(file_or_path, e.message)
15
22
  end
23
+
24
+ def self.file?(object)
25
+ object.respond_to?(:path) && object.respond_to?(:read)
26
+ end
27
+ private_class_method :file?
16
28
  end
17
29
  end
18
30
  end
@@ -7,13 +7,23 @@ module Asimov
7
7
  # more specific file validators.
8
8
  ##
9
9
  class JsonlValidator
10
- def validate(file)
11
- file.each_line.with_index { |line, idx| validate_line(line, idx) }
10
+ ##
11
+ # Validate that the IO object (typically a File) is properly
12
+ # formatted. Entry method for this class and its subclasses.
13
+ # Required format will depend on the class.
14
+ #
15
+ # @param [IO] io IO object, typically a file, whose contents
16
+ # are to be format checked.
17
+ ##
18
+ def validate(io)
19
+ io.each_line.with_index { |line, idx| validate_line(line, idx) }
12
20
  true
13
21
  rescue JSON::ParserError
14
22
  raise JsonlFileCannotBeParsedError, "Expected file to have the JSONL format."
15
23
  end
16
24
 
25
+ private
26
+
17
27
  def validate_line(line, idx)
18
28
  JSON.parse(line)
19
29
  rescue JSON::ParserError
@@ -14,6 +14,16 @@ module Asimov
14
14
  ALLOWED_OPTIONS = %i[timeout open_timeout read_timeout write_timeout local_host local_port
15
15
  verify verify_peer ssl_ca_file ssl_ca_path ssl_version ciphers
16
16
  http_proxyaddr http_proxyport http_proxyuser http_proxypass].freeze
17
+
18
+ ##
19
+ # Validates that the options are allowed request
20
+ # options. Currently checks the keys - both that they are symbols and that
21
+ # they are allowed options. Does not validate values.
22
+ #
23
+ # Only entry point for this class.
24
+ #
25
+ # @param [Hash] options the set of request options to validate
26
+ ##
17
27
  def self.validate(options)
18
28
  unless options.is_a?(Hash)
19
29
  raise Asimov::ConfigurationError,
@@ -32,6 +42,7 @@ module Asimov
32
42
  end
33
43
  unsupported_options
34
44
  end
45
+ private_class_method :generate_unsupported_options
35
46
 
36
47
  def self.check_unsupported_options(unsupported_options)
37
48
  return if unsupported_options.empty?
@@ -40,6 +51,7 @@ module Asimov
40
51
  raise Asimov::ConfigurationError,
41
52
  "The options #{quoted_keys.join(',')} are not supported."
42
53
  end
54
+ private_class_method :check_unsupported_options
43
55
 
44
56
  def self.supported_option?(key)
45
57
  ALLOWED_OPTIONS.include?(key)
@@ -51,6 +63,7 @@ module Asimov
51
63
  raise Asimov::ConfigurationError,
52
64
  "Request options keys must be symbols. The key '#{key}' is not a symbol."
53
65
  end
66
+ private_class_method :check_symbol
54
67
  end
55
68
  end
56
69
  end
@@ -10,6 +10,8 @@ module Asimov
10
10
  # any value. No other keys are permitted.
11
11
  ##
12
12
  class TextEntryFileValidator < JsonlValidator
13
+ private
14
+
13
15
  def validate_line(line, idx)
14
16
  parsed = JSON.parse(line)
15
17
  validate_text_entry(parsed, idx)
@@ -9,6 +9,8 @@ module Asimov
9
9
  # values. No other keys are permitted.
10
10
  ##
11
11
  class TrainingFileValidator < JsonlValidator
12
+ private
13
+
12
14
  def validate_line(line, idx)
13
15
  parsed = JSON.parse(line)
14
16
  validate_training_example(parsed, idx)
@@ -1,3 +1,4 @@
1
1
  module Asimov
2
- VERSION = "0.1.0".freeze
2
+ # Current gem version
3
+ VERSION = "1.1.0".freeze
3
4
  end
data/lib/asimov.rb CHANGED
@@ -4,7 +4,7 @@ require_relative "asimov/error"
4
4
  require_relative "asimov/client"
5
5
 
6
6
  ##
7
- # Client library for using the OpenAI API.
7
+ # Top level module for the Asimov client library for using the OpenAI API.
8
8
  ##
9
9
  module Asimov
10
10
  ##