lib/openai/files.rb in ruby-openai-6.5.0 vs lib/openai/files.rb in ruby-openai-7.0.0
- old
+ new
@@ -1,22 +1,33 @@
module OpenAI
class Files
+ PURPOSES = %w[
+ assistants
+ batch
+ fine-tune
+ ].freeze
+
def initialize(client:)
@client = client
end
def list
@client.get(path: "/files")
end
def upload(parameters: {})
- validate(file: parameters[:file]) if parameters[:file].include?(".jsonl")
+ file_input = parameters[:file]
+ file = prepare_file_input(file_input: file_input)
+ validate(file: file, purpose: parameters[:purpose], file_input: file_input)
+
@client.multipart_post(
path: "/files",
- parameters: parameters.merge(file: File.open(parameters[:file]))
+ parameters: parameters.merge(file: file)
)
+ ensure
+ file.close if file.is_a?(File)
end
def retrieve(id:)
@client.get(path: "/files/#{id}")
end
@@ -29,14 +40,35 @@
@client.delete(path: "/files/#{id}")
end
private
- def validate(file:)
- File.open(file).each_line.with_index do |line, index|
+ def prepare_file_input(file_input:)
+ if file_input.is_a?(String)
+ File.open(file_input)
+ elsif file_input.respond_to?(:read) && file_input.respond_to?(:rewind)
+ file_input
+ else
+ raise ArgumentError, "Invalid file - must be a StringIO object or a path to a file."
+ end
+ end
+
+ def validate(file:, purpose:, file_input:)
+ raise ArgumentError, "`file` is required" if file.nil?
+ unless PURPOSES.include?(purpose)
+ raise ArgumentError, "`purpose` must be one of `#{PURPOSES.join(',')}`"
+ end
+
+ validate_jsonl(file: file) if file_input.is_a?(String) && file_input.end_with?(".jsonl")
+ end
+
+ def validate_jsonl(file:)
+ file.each_line.with_index do |line, index|
JSON.parse(line)
rescue JSON::ParserError => e
raise JSON::ParserError, "#{e.message} - found on line #{index + 1} of #{file}"
end
+ ensure
+ file.rewind
end
end
end