forked from alexrudall/ruby-openai
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request alexrudall#234 from alexrudall/faraday
Add streaming with Faraday
- Loading branch information
Showing
60 changed files
with
64,536 additions
and
1,422 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
module OpenAI | ||
module HTTP | ||
def get(path:) | ||
to_json(conn.get(uri(path: path)) do |req| | ||
req.headers = headers | ||
end&.body) | ||
end | ||
|
||
def json_post(path:, parameters:) | ||
to_json(conn.post(uri(path: path)) do |req| | ||
if parameters[:stream].is_a?(Proc) | ||
req.options.on_data = to_json_stream(user_proc: parameters[:stream]) | ||
parameters[:stream] = true # Necessary to tell OpenAI to stream. | ||
end | ||
|
||
req.headers = headers | ||
req.body = parameters.to_json | ||
end&.body) | ||
end | ||
|
||
def multipart_post(path:, parameters: nil) | ||
to_json(conn(multipart: true).post(uri(path: path)) do |req| | ||
req.headers = headers.merge({ "Content-Type" => "multipart/form-data" }) | ||
req.body = multipart_parameters(parameters) | ||
end&.body) | ||
end | ||
|
||
def delete(path:) | ||
to_json(conn.delete(uri(path: path)) do |req| | ||
req.headers = headers | ||
end&.body) | ||
end | ||
|
||
private | ||
|
||
def to_json(string) | ||
return unless string | ||
|
||
JSON.parse(string) | ||
rescue JSON::ParserError | ||
# Convert a multiline string of JSON objects to a JSON array. | ||
JSON.parse(string.gsub("}\n{", "},{").prepend("[").concat("]")) | ||
end | ||
|
||
# Given a proc, returns an outer proc that can be used to iterate over a JSON stream of chunks. | ||
# For each chunk, the inner user_proc is called giving it the JSON object. The JSON object could | ||
# be a data object or an error object as described in the OpenAI API documentation. | ||
# | ||
# If the JSON object for a given data or error message is invalid, it is ignored. | ||
# | ||
# @param user_proc [Proc] The inner proc to call for each JSON object in the chunk. | ||
# @return [Proc] An outer proc that iterates over a raw stream, converting it to JSON. | ||
def to_json_stream(user_proc:) | ||
proc do |chunk, _| | ||
chunk.scan(/(?:data|error): (\{.*\})/i).flatten.each do |data| | ||
user_proc.call(JSON.parse(data)) | ||
rescue JSON::ParserError | ||
# Ignore invalid JSON. | ||
end | ||
end | ||
end | ||
|
||
def conn(multipart: false) | ||
Faraday.new do |f| | ||
f.options[:timeout] = OpenAI.configuration.request_timeout | ||
f.request(:multipart) if multipart | ||
end | ||
end | ||
|
||
def uri(path:) | ||
OpenAI.configuration.uri_base + OpenAI.configuration.api_version + path | ||
end | ||
|
||
def headers | ||
{ | ||
"Content-Type" => "application/json", | ||
"Authorization" => "Bearer #{OpenAI.configuration.access_token}", | ||
"OpenAI-Organization" => OpenAI.configuration.organization_id | ||
} | ||
end | ||
|
||
def multipart_parameters(parameters) | ||
parameters&.transform_values do |value| | ||
next value unless value.is_a?(File) | ||
|
||
# Doesn't seem like OpenAI need mime_type yet, so not worth | ||
# the library to figure this out. Hence the empty string | ||
# as the second argument. | ||
Faraday::UploadIO.new(value, "", value.path) | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
module OpenAI | ||
VERSION = "3.7.0".freeze | ||
VERSION = "4.0.0".freeze | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.