Skip to content

Commit a22138a

Browse files
committed
Raise errors on HTTP errors or JSON parse errors
1 parent 4bc3466 commit a22138a

File tree

5 files changed

+75
-35
lines changed

5 files changed

+75
-35
lines changed

lib/openai/http.rb

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -59,25 +59,21 @@ def to_json_stream(user_proc:)
5959

6060
proc do |chunk, _bytes, env|
6161
if env && env.status != 200
62-
emit_json(json: chunk, user_proc: user_proc)
63-
else
64-
parser.feed(chunk) do |_type, data|
65-
emit_json(json: data, user_proc: user_proc) unless data == "[DONE]"
66-
end
62+
raise_error = Faraday::Response::RaiseError.new
63+
raise_error.on_complete(env.merge(body: JSON.parse(chunk)))
6764
end
68-
end
69-
end
7065

71-
def emit_json(json:, user_proc:)
72-
user_proc.call(JSON.parse(json))
73-
rescue JSON::ParserError
74-
# Ignore invalid JSON.
66+
parser.feed(chunk) do |_type, data|
67+
user_proc.call(JSON.parse(data)) unless data == "[DONE]"
68+
end
69+
end
7570
end
7671

7772
def conn(multipart: false)
7873
Faraday.new do |f|
7974
f.options[:timeout] = @request_timeout
8075
f.request(:multipart) if multipart
76+
f.response :raise_error
8177
end
8278
end
8379

spec/fixtures/cassettes/gpt-3_5-turbo_streamed_chat_with_error_response.yml

Lines changed: 42 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

spec/openai/client/chat_spec.rb

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,28 @@ def call(chunk)
7272
end
7373
end
7474
end
75+
76+
context "with an error response" do
77+
let(:cassette) { "#{model} streamed chat with error response".downcase }
78+
79+
it "raises an HTTP error" do
80+
VCR.use_cassette(cassette) do
81+
response
82+
rescue Faraday::BadRequestError => e
83+
expect(e.response).to include(status: 400)
84+
expect(e.response[:body]).to eq({
85+
"error" => {
86+
"message" => "Test error",
87+
"type" => "test_error",
88+
"param" => nil,
89+
"code" => "test"
90+
}
91+
})
92+
else
93+
raise "Expected to raise Faraday::BadRequestError"
94+
end
95+
end
96+
end
7597
end
7698
end
7799

spec/openai/client/finetunes_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,9 @@
8181

8282
# It takes too long to fine-tune a model so we can delete it when running the test suite
8383
# against the live API. Instead, we just check that the API returns an error.
84-
it "returns an error" do
84+
it "raises an error" do
8585
VCR.use_cassette(cassette) do
86-
expect(response.dig("error", "message")).to include("does not exist")
86+
expect { response }.to raise_error(Faraday::ResourceNotFound)
8787
end
8888
end
8989

spec/openai/client/http_spec.rb

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -144,32 +144,12 @@
144144
CHUNK
145145
end
146146

147-
it "does not raise an error" do
147+
it "raise an error" do
148148
expect(user_proc).to receive(:call).with(JSON.parse('{"foo": "bar"}'))
149149

150150
expect do
151151
stream.call(chunk)
152-
end.not_to raise_error
153-
end
154-
end
155-
156-
context "wehn called with string containing Obie's invalid JSON" do
157-
let(:chunk) do
158-
<<~CHUNK
159-
data: { "foo": "bar" }
160-
161-
data: {"id":"chatcmpl-123","object":"chat.completion.chunk","created":123,"model":"gpt-4","choices":[{"index":0,"delta":{"role":"assistant","content":null,"fu
162-
163-
#
164-
CHUNK
165-
end
166-
167-
it "does not raise an error" do
168-
expect(user_proc).to receive(:call).with(JSON.parse('{"foo": "bar"}'))
169-
170-
expect do
171-
stream.call(chunk)
172-
end.not_to raise_error
152+
end.to raise_error(JSON::ParserError)
173153
end
174154
end
175155

0 commit comments

Comments
 (0)