11module OpenAI
22 class Files
3+
4+ PURPOSES = %w[ fine-tune assistants ] . freeze
5+
36 def initialize ( client :)
47 @client = client
58 end
@@ -9,12 +12,17 @@ def list
912 end
1013
1114 def upload ( parameters : { } )
12- validate ( file : parameters [ :file ] ) if parameters [ :file ] . include? ( ".jsonl" )
15+ file_input = parameters [ :file ]
16+ file = prepare_file_input ( file_input : file_input )
17+
18+ validate ( file : file , purpose : parameters [ :purpose ] , file_input : file_input )
1319
1420 @client . multipart_post (
1521 path : "/files" ,
16- parameters : parameters . merge ( file : File . open ( parameters [ : file] ) )
22+ parameters : parameters . merge ( file : file )
1723 )
24+ ensure
25+ file . close if file . is_a? ( File )
1826 end
1927
2028 def retrieve ( id :)
@@ -31,12 +39,31 @@ def delete(id:)
3139
3240 private
3341
34- def validate ( file :)
35- File . open ( file ) . each_line . with_index do |line , index |
42+ def prepare_file_input ( file_input :)
43+ if file_input . is_a? ( String )
44+ File . open ( file_input )
45+ elsif file_input . respond_to? ( :read ) && file_input . respond_to? ( :rewind )
46+ file_input
47+ else
48+ raise ArgumentError , "Invalid file input"
49+ end
50+ end
51+
52+ def validate ( file :, purpose :, file_input :)
53+ raise ArgumentError , "`file` is required" if file . nil?
54+ raise ArgumentError , "`purpose` must one of `#{ PURPOSES . join ( ',' ) } `" unless PURPOSES . include? ( purpose )
55+
56+ validate_jsonl ( file : file ) if file_input . is_a? ( String ) && file_input . end_with? ( ".jsonl" )
57+ end
58+
59+ def validate_jsonl ( file :)
60+ file . each_line . with_index do |line , index |
3661 JSON . parse ( line )
3762 rescue JSON ::ParserError => e
3863 raise JSON ::ParserError , "#{ e . message } - found on line #{ index + 1 } of #{ file } "
3964 end
65+ ensure
66+ file . rewind
4067 end
4168 end
4269end
0 commit comments