Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions lib/openai/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,16 @@ def initialize(config = {}, &faraday_middleware)
@faraday_middleware = faraday_middleware
end

def chat(parameters: {})
json_post(path: "/chat/completions", parameters: parameters)
def chat(parameters: {}, extra_headers: {})
json_post(path: "/chat/completions", parameters: parameters, extra_headers: extra_headers)
end

def embeddings(parameters: {})
json_post(path: "/embeddings", parameters: parameters)
def embeddings(parameters: {}, extra_headers: {})
json_post(path: "/embeddings", parameters: parameters, extra_headers: extra_headers)
end

def completions(parameters: {})
json_post(path: "/completions", parameters: parameters)
def completions(parameters: {}, extra_headers: {})
json_post(path: "/completions", parameters: parameters, extra_headers: extra_headers)
end

def audio
Expand Down Expand Up @@ -97,8 +97,8 @@ def realtime
@realtime ||= OpenAI::Realtime.new(client: self)
end

def moderations(parameters: {})
json_post(path: "/moderations", parameters: parameters)
def moderations(parameters: {}, extra_headers: {})
json_post(path: "/moderations", parameters: parameters, extra_headers: extra_headers)
end

def usage
Expand Down
24 changes: 12 additions & 12 deletions lib/openai/http.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,35 @@ module OpenAI
module HTTP
include HTTPHeaders

def get(path:, parameters: nil)
def get(path:, parameters: nil, extra_headers: {})
parse_json(conn.get(uri(path: path), parameters) do |req|
req.headers = headers
req.headers = headers.merge!(extra_headers)
end&.body)
end

def post(path:)
def post(path:, extra_headers: {})
parse_json(conn.post(uri(path: path)) do |req|
req.headers = headers
req.headers = headers.merge!(extra_headers)
end&.body)
end

def json_post(path:, parameters:, query_parameters: {})
def json_post(path:, parameters:, query_parameters: {}, extra_headers: {})
parse_json(conn.post(uri(path: path)) do |req|
configure_json_post_request(req, parameters)
configure_json_post_request(req, parameters, extra_headers: extra_headers)
req.params = req.params.merge(query_parameters)
end&.body)
end

def multipart_post(path:, parameters: nil)
def multipart_post(path:, parameters: nil, extra_headers: {})
parse_json(conn(multipart: true).post(uri(path: path)) do |req|
req.headers = headers.merge({ "Content-Type" => "multipart/form-data" })
req.headers = headers.merge("Content-Type" => "multipart/form-data").merge!(extra_headers)
req.body = multipart_parameters(parameters)
end&.body)
end

def delete(path:)
def delete(path:, extra_headers: {})
parse_json(conn.delete(uri(path: path)) do |req|
req.headers = headers
req.headers = headers.merge!(extra_headers)
end&.body)
end

Expand Down Expand Up @@ -95,7 +95,7 @@ def multipart_parameters(parameters)
end
end

def configure_json_post_request(req, parameters)
def configure_json_post_request(req, parameters, extra_headers: {})
req_parameters = parameters.dup

if parameters[:stream].respond_to?(:call)
Expand All @@ -105,7 +105,7 @@ def configure_json_post_request(req, parameters)
raise ArgumentError, "The stream parameter must be a Proc or have a #call method"
end

req.headers = headers
req.headers = headers.merge!(extra_headers)
req.body = req_parameters.to_json
end
end
Expand Down
43 changes: 43 additions & 0 deletions spec/openai/client/http_spec.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,47 @@
RSpec.describe OpenAI::HTTP do
describe "extra_headers" do
include WebMock::API

let(:client) { OpenAI::Client.new }
let(:custom_headers) { { "X-Custom-Header" => "custom-value", "X-Another" => "another-value" } }
let(:chat_url) { "https://api.openai.com/v1/chat/completions" }

before do
VCR.turn_off!
WebMock.disable_net_connect!
stub_request(:post, chat_url)
.to_return(status: 200, body: { choices: [] }.to_json, headers: {})
end

after do
WebMock.reset!
VCR.turn_on!
end

it "merges extra_headers into the request" do
client.chat(parameters: { model: "gpt-4", messages: [] }, extra_headers: custom_headers)

assert_requested(:post, chat_url, headers: custom_headers)
end

it "allows extra_headers to override default headers" do
client.chat(
parameters: { model: "gpt-4", messages: [] },
extra_headers: { "Content-Type" => "application/json; charset=utf-8" }
)

assert_requested(
:post, chat_url, headers: { "Content-Type" => "application/json; charset=utf-8" }
)
end

it "works without extra_headers (backward compatible)" do
client.chat(parameters: { model: "gpt-4", messages: [] })

assert_requested(:post, chat_url)
end
end

describe "with an aggressive timeout" do
let(:timeout_errors) { [Faraday::ConnectionFailed, Faraday::TimeoutError] }
let(:timeout) { 0 }
Expand Down