ruby-openai 5.1.0 → 6.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.devcontainer/Dockerfile +16 -0
- data/.devcontainer/devcontainer.json +36 -0
- data/.devcontainer/docker-compose.yml +19 -0
- data/.github/FUNDING.yml +13 -0
- data/CHANGELOG.md +20 -0
- data/Gemfile +2 -2
- data/Gemfile.lock +13 -9
- data/README.md +28 -33
- data/lib/openai/client.rb +0 -4
- data/lib/openai/finetunes.rb +6 -14
- data/lib/openai/http.rb +42 -28
- data/lib/openai/version.rb +1 -1
- data/ruby-openai.gemspec +1 -0
- metadata +31 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 88af78318c57c49636755099d6c8837e62762dee65e27465160b1d3778721edd
|
4
|
+
data.tar.gz: d6abf778678cf1813ce61efcf5874ecb0e4157a9cb08f6e958948b6d4f5d74ab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 046c91484f51ea3973698c2bd3a7ff627df3a8413097757e4cd7debaf540ee40eb162cfdc6df41b2973cba3a5ef17014c8c18f544c777a5a45d93cb8530fe232
|
7
|
+
data.tar.gz: 196cd9c830e5e2639c16fc02431b2dfad8286cc098c85b47c6c42c2c64a2f570a8412f021846ffdff0c057a184a298c43c82e69b0f2ad1b25f048b0c76969422
|
@@ -0,0 +1,16 @@
|
|
1
|
+
FROM ruby:3.2.2-slim-bullseye
|
2
|
+
|
3
|
+
ENV TZ="Europe/London"
|
4
|
+
|
5
|
+
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
|
6
|
+
&& apt-get -y install --no-install-recommends \
|
7
|
+
apt-utils \
|
8
|
+
build-essential \
|
9
|
+
curl \
|
10
|
+
git \
|
11
|
+
vim \
|
12
|
+
zsh
|
13
|
+
|
14
|
+
RUN gem install bundler
|
15
|
+
|
16
|
+
WORKDIR /workspace
|
@@ -0,0 +1,36 @@
|
|
1
|
+
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
|
2
|
+
// https://github.com/microsoft/vscode-dev-containers/tree/v0.245.2/containers/ruby-rails-postgres
|
3
|
+
// Update the VARIANT arg in docker-compose.yml to pick a Ruby version
|
4
|
+
{
|
5
|
+
"name": "ruby-openai",
|
6
|
+
"dockerComposeFile": "docker-compose.yml",
|
7
|
+
"service": "app",
|
8
|
+
"workspaceFolder": "/workspace",
|
9
|
+
"containerEnv": {
|
10
|
+
"GITHUB_TOKEN": "${localEnv:GITHUB_TOKEN}",
|
11
|
+
"GITHUB_USER": "${localEnv:GITHUB_USER}"
|
12
|
+
},
|
13
|
+
// Configure tool-specific properties.
|
14
|
+
"customizations": {
|
15
|
+
// Configure properties specific to VS Code.
|
16
|
+
"vscode": {
|
17
|
+
// Add the IDs of extensions you want installed when the container is created.
|
18
|
+
"extensions": [
|
19
|
+
"rebornix.Ruby",
|
20
|
+
"sleistner.vscode-fileutils",
|
21
|
+
"ms-azuretools.vscode-docker",
|
22
|
+
"samverschueren.final-newline",
|
23
|
+
"GitHub.copilot",
|
24
|
+
"usernamehw.remove-empty-lines",
|
25
|
+
"wingrunr21.vscode-ruby",
|
26
|
+
]
|
27
|
+
}
|
28
|
+
},
|
29
|
+
// Use 'postCreateCommand' to run commands after the container is created.
|
30
|
+
"postCreateCommand": "bundle install",
|
31
|
+
// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
|
32
|
+
"features": {
|
33
|
+
"git": "os-provided",
|
34
|
+
"github-cli": "latest"
|
35
|
+
}
|
36
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
version: "3"
|
2
|
+
|
3
|
+
services:
|
4
|
+
app:
|
5
|
+
build:
|
6
|
+
context: ..
|
7
|
+
dockerfile: .devcontainer/Dockerfile
|
8
|
+
|
9
|
+
volumes:
|
10
|
+
- ..:/workspace:cached
|
11
|
+
- bundle_cache:/bundle
|
12
|
+
|
13
|
+
command: sleep infinity
|
14
|
+
|
15
|
+
environment:
|
16
|
+
TZ: Europe/London
|
17
|
+
|
18
|
+
volumes:
|
19
|
+
bundle_cache:
|
data/.github/FUNDING.yml
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# These are supported funding model platforms
|
2
|
+
|
3
|
+
github: alexrudall
|
4
|
+
patreon: # Replace with a single Patreon username
|
5
|
+
open_collective: # Replace with a single Open Collective username
|
6
|
+
ko_fi: # Replace with a single Ko-fi username
|
7
|
+
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
8
|
+
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
9
|
+
liberapay: # Replace with a single Liberapay username
|
10
|
+
issuehunt: # Replace with a single IssueHunt username
|
11
|
+
otechie: # Replace with a single Otechie username
|
12
|
+
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
13
|
+
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
data/CHANGELOG.md
CHANGED
@@ -5,6 +5,26 @@ All notable changes to this project will be documented in this file.
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
7
|
|
8
|
+
## [6.0.0] - 2023-11-06
|
9
|
+
|
10
|
+
### Added
|
11
|
+
|
12
|
+
- [BREAKING] HTTP errors will now be raised by ruby-openai as Faraday:Errors, including when streaming! Implemented by [@atesgoral](https://github.com/atesgoral)
|
13
|
+
- [BREAKING] Switch from legacy Finetunes to the new Fine-tune-jobs endpoints. Implemented by [@lancecarlson](https://github.com/lancecarlson)
|
14
|
+
- [BREAKING] Remove deprecated Completions endpoints - use Chat instead.
|
15
|
+
|
16
|
+
### Fix
|
17
|
+
|
18
|
+
- [BREAKING] Fix issue where :stream parameters where replaced by a boolean in the client application. Thanks to [@martinjaimem](https://github.com/martinjaimem), [@vickymadrid03](https://github.com/vickymadrid03) and [@nicastelo](https://github.com/nicastelo) for spotting and fixing this issue.
|
19
|
+
|
20
|
+
## [5.2.0] - 2023-10-30
|
21
|
+
|
22
|
+
### Fix
|
23
|
+
|
24
|
+
- Added more spec-compliant SSE parsing: see here https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation
|
25
|
+
- Fixes issue where OpenAI or an intermediary returns only partial JSON per chunk of streamed data
|
26
|
+
- Huge thanks to [@atesgoral](https://github.com/atesgoral) for this important fix!
|
27
|
+
|
8
28
|
## [5.1.0] - 2023-08-20
|
9
29
|
|
10
30
|
### Added
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,22 +1,26 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
ruby-openai (
|
4
|
+
ruby-openai (6.0.0)
|
5
|
+
event_stream_parser (>= 0.3.0, < 1.0.0)
|
5
6
|
faraday (>= 1)
|
6
7
|
faraday-multipart (>= 1)
|
7
8
|
|
8
9
|
GEM
|
9
10
|
remote: https://rubygems.org/
|
10
11
|
specs:
|
11
|
-
addressable (2.8.
|
12
|
+
addressable (2.8.5)
|
12
13
|
public_suffix (>= 2.0.2, < 6.0)
|
13
14
|
ast (2.4.2)
|
15
|
+
base64 (0.1.1)
|
14
16
|
byebug (11.1.3)
|
15
17
|
crack (0.4.5)
|
16
18
|
rexml
|
17
19
|
diff-lcs (1.5.0)
|
18
20
|
dotenv (2.8.1)
|
19
|
-
|
21
|
+
event_stream_parser (0.3.0)
|
22
|
+
faraday (2.7.11)
|
23
|
+
base64
|
20
24
|
faraday-net_http (>= 2.0, < 3.1)
|
21
25
|
ruby2_keywords (>= 0.0.4)
|
22
26
|
faraday-multipart (1.0.4)
|
@@ -28,11 +32,11 @@ GEM
|
|
28
32
|
parallel (1.22.1)
|
29
33
|
parser (3.2.2.0)
|
30
34
|
ast (~> 2.4.1)
|
31
|
-
public_suffix (5.0.
|
35
|
+
public_suffix (5.0.3)
|
32
36
|
rainbow (3.1.1)
|
33
|
-
rake (13.0
|
37
|
+
rake (13.1.0)
|
34
38
|
regexp_parser (2.8.0)
|
35
|
-
rexml (3.2.
|
39
|
+
rexml (3.2.6)
|
36
40
|
rspec (3.12.0)
|
37
41
|
rspec-core (~> 3.12.0)
|
38
42
|
rspec-expectations (~> 3.12.0)
|
@@ -62,7 +66,7 @@ GEM
|
|
62
66
|
ruby2_keywords (0.0.5)
|
63
67
|
unicode-display_width (2.4.2)
|
64
68
|
vcr (6.1.0)
|
65
|
-
webmock (3.
|
69
|
+
webmock (3.19.1)
|
66
70
|
addressable (>= 2.8.0)
|
67
71
|
crack (>= 0.3.2)
|
68
72
|
hashdiff (>= 0.4.0, < 2.0.0)
|
@@ -73,12 +77,12 @@ PLATFORMS
|
|
73
77
|
DEPENDENCIES
|
74
78
|
byebug (~> 11.1.3)
|
75
79
|
dotenv (~> 2.8.1)
|
76
|
-
rake (~> 13.
|
80
|
+
rake (~> 13.1)
|
77
81
|
rspec (~> 3.12)
|
78
82
|
rubocop (~> 1.50.2)
|
79
83
|
ruby-openai!
|
80
84
|
vcr (~> 6.1.0)
|
81
|
-
webmock (~> 3.
|
85
|
+
webmock (~> 3.19.1)
|
82
86
|
|
83
87
|
BUNDLED WITH
|
84
88
|
2.4.5
|
data/README.md
CHANGED
@@ -8,11 +8,9 @@ Use the [OpenAI API](https://openai.com/blog/openai-api/) with Ruby! 🤖❤️
|
|
8
8
|
|
9
9
|
Stream text with GPT-4, transcribe and translate audio with Whisper, or create images with DALL·E...
|
10
10
|
|
11
|
-
|
11
|
+
🚢 Based in the UK and want to hire me? Now you can! [railsai.com](https://railsai.com?utm_source=ruby-openai&utm_medium=readme&utm_id=26072023)
|
12
12
|
|
13
|
-
[
|
14
|
-
|
15
|
-
Follow me on [Twitter](https://twitter.com/alexrudall) for more Ruby / AI content
|
13
|
+
[🎮 Ruby AI Builders Discord](https://discord.gg/k4Uc224xVD) | [🐦 Twitter](https://twitter.com/alexrudall) | [🧠 Anthropic Gem](https://github.com/alexrudall/anthropic) | [🚂 Midjourney Gem](https://github.com/alexrudall/midjourney)
|
16
14
|
|
17
15
|
### Bundler
|
18
16
|
|
@@ -151,7 +149,7 @@ client.models.retrieve(id: "text-ada-001")
|
|
151
149
|
#### Examples
|
152
150
|
|
153
151
|
- [GPT-4 (limited beta)](https://platform.openai.com/docs/models/gpt-4)
|
154
|
-
- gpt-4
|
152
|
+
- gpt-4 (uses current version)
|
155
153
|
- gpt-4-0314
|
156
154
|
- gpt-4-32k
|
157
155
|
- [GPT-3.5](https://platform.openai.com/docs/models/gpt-3-5)
|
@@ -163,9 +161,9 @@ client.models.retrieve(id: "text-ada-001")
|
|
163
161
|
- text-babbage-001
|
164
162
|
- text-curie-001
|
165
163
|
|
166
|
-
###
|
164
|
+
### Chat
|
167
165
|
|
168
|
-
|
166
|
+
GPT is a model that can be used to generate text in a conversational style. You can use it to [generate a response](https://platform.openai.com/docs/api-reference/chat/create) to a sequence of [messages](https://platform.openai.com/docs/guides/chat/introduction):
|
169
167
|
|
170
168
|
```ruby
|
171
169
|
response = client.chat(
|
@@ -178,11 +176,11 @@ puts response.dig("choices", 0, "message", "content")
|
|
178
176
|
# => "Hello! How may I assist you today?"
|
179
177
|
```
|
180
178
|
|
181
|
-
### Streaming
|
179
|
+
### Streaming Chat
|
182
180
|
|
183
|
-
[Quick guide to streaming
|
181
|
+
[Quick guide to streaming Chat with Rails 7 and Hotwire](https://gist.github.com/alexrudall/cb5ee1e109353ef358adb4e66631799d)
|
184
182
|
|
185
|
-
You can stream from the API in realtime, which can be much faster and used to create a more engaging user experience. Pass a [Proc](https://ruby-doc.org/core-2.6/Proc.html) (or any object with a `#call` method) to the `stream` parameter to receive the stream of
|
183
|
+
You can stream from the API in realtime, which can be much faster and used to create a more engaging user experience. Pass a [Proc](https://ruby-doc.org/core-2.6/Proc.html) (or any object with a `#call` method) to the `stream` parameter to receive the stream of completion chunks as they are generated. Each time one or more chunks is received, the proc will be called once with each chunk, parsed as a Hash. If OpenAI returns an error, `ruby-openai` will raise a Faraday error.
|
186
184
|
|
187
185
|
```ruby
|
188
186
|
client.chat(
|
@@ -197,7 +195,7 @@ client.chat(
|
|
197
195
|
# => "Anna is a young woman in her mid-twenties, with wavy chestnut hair that falls to her shoulders..."
|
198
196
|
```
|
199
197
|
|
200
|
-
Note:
|
198
|
+
Note: OpenAPI currently does not report token usage for streaming responses. To count tokens while streaming, try `OpenAI.rough_token_count` or [tiktoken_ruby](https://github.com/IAPark/tiktoken_ruby). We think that each call to the stream proc corresponds to a single token, so you can also try counting the number of calls to the proc to get the completion token count.
|
201
199
|
|
202
200
|
### Functions
|
203
201
|
|
@@ -259,21 +257,6 @@ end
|
|
259
257
|
# => "The weather is nice 🌞"
|
260
258
|
```
|
261
259
|
|
262
|
-
### Completions
|
263
|
-
|
264
|
-
Hit the OpenAI API for a completion using other GPT-3 models:
|
265
|
-
|
266
|
-
```ruby
|
267
|
-
response = client.completions(
|
268
|
-
parameters: {
|
269
|
-
model: "text-davinci-001",
|
270
|
-
prompt: "Once upon a time",
|
271
|
-
max_tokens: 5
|
272
|
-
})
|
273
|
-
puts response["choices"].map { |c| c["text"] }
|
274
|
-
# => [", there lived a great"]
|
275
|
-
```
|
276
|
-
|
277
260
|
### Edits
|
278
261
|
|
279
262
|
Send a string and some instructions for what to do to the string:
|
@@ -325,22 +308,22 @@ client.files.content(id: "file-123")
|
|
325
308
|
client.files.delete(id: "file-123")
|
326
309
|
```
|
327
310
|
|
328
|
-
###
|
311
|
+
### Finetunes
|
329
312
|
|
330
313
|
Upload your fine-tuning data in a `.jsonl` file as above and get its ID:
|
331
314
|
|
332
315
|
```ruby
|
333
|
-
response = client.files.upload(parameters: { file: "path/to/
|
316
|
+
response = client.files.upload(parameters: { file: "path/to/sarcasm.jsonl", purpose: "fine-tune" })
|
334
317
|
file_id = JSON.parse(response.body)["id"]
|
335
318
|
```
|
336
319
|
|
337
|
-
You can then use this file ID to create a fine
|
320
|
+
You can then use this file ID to create a fine tuning job:
|
338
321
|
|
339
322
|
```ruby
|
340
323
|
response = client.finetunes.create(
|
341
324
|
parameters: {
|
342
325
|
training_file: file_id,
|
343
|
-
model: "
|
326
|
+
model: "gpt-3.5-turbo-0613"
|
344
327
|
})
|
345
328
|
fine_tune_id = response["id"]
|
346
329
|
```
|
@@ -371,10 +354,10 @@ response = client.completions(
|
|
371
354
|
response.dig("choices", 0, "text")
|
372
355
|
```
|
373
356
|
|
374
|
-
You can
|
357
|
+
You can also capture the events for a job:
|
375
358
|
|
376
|
-
```
|
377
|
-
client.finetunes.
|
359
|
+
```
|
360
|
+
client.finetunes.list_events(id: fine_tune_id)
|
378
361
|
```
|
379
362
|
|
380
363
|
### Image Generation
|
@@ -457,6 +440,18 @@ puts response["text"]
|
|
457
440
|
# => "Transcription of the text"
|
458
441
|
```
|
459
442
|
|
443
|
+
#### Errors
|
444
|
+
|
445
|
+
HTTP errors can be caught like this:
|
446
|
+
|
447
|
+
```
|
448
|
+
begin
|
449
|
+
OpenAI::Client.new.models.retrieve(id: "text-ada-001")
|
450
|
+
rescue Faraday::Error => e
|
451
|
+
raise "Got a Faraday error: #{e}"
|
452
|
+
end
|
453
|
+
```
|
454
|
+
|
460
455
|
## Development
|
461
456
|
|
462
457
|
After checking out the repo, run `bin/setup` to install dependencies. You can run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/lib/openai/client.rb
CHANGED
@@ -25,10 +25,6 @@ module OpenAI
|
|
25
25
|
json_post(path: "/chat/completions", parameters: parameters)
|
26
26
|
end
|
27
27
|
|
28
|
-
def completions(parameters: {})
|
29
|
-
json_post(path: "/completions", parameters: parameters)
|
30
|
-
end
|
31
|
-
|
32
28
|
def edits(parameters: {})
|
33
29
|
json_post(path: "/edits", parameters: parameters)
|
34
30
|
end
|
data/lib/openai/finetunes.rb
CHANGED
@@ -5,31 +5,23 @@ module OpenAI
|
|
5
5
|
end
|
6
6
|
|
7
7
|
def list
|
8
|
-
@client.get(path: "/
|
8
|
+
@client.get(path: "/fine_tuning/jobs")
|
9
9
|
end
|
10
10
|
|
11
11
|
def create(parameters: {})
|
12
|
-
@client.json_post(path: "/
|
12
|
+
@client.json_post(path: "/fine_tuning/jobs", parameters: parameters)
|
13
13
|
end
|
14
14
|
|
15
15
|
def retrieve(id:)
|
16
|
-
@client.get(path: "/
|
16
|
+
@client.get(path: "/fine_tuning/jobs/#{id}")
|
17
17
|
end
|
18
18
|
|
19
19
|
def cancel(id:)
|
20
|
-
@client.
|
20
|
+
@client.json_post(path: "/fine_tuning/jobs/#{id}/cancel", parameters: {})
|
21
21
|
end
|
22
22
|
|
23
|
-
def
|
24
|
-
@client.get(path: "/
|
25
|
-
end
|
26
|
-
|
27
|
-
def delete(fine_tuned_model:)
|
28
|
-
if fine_tuned_model.start_with?("ft-")
|
29
|
-
raise ArgumentError, "Please give a fine_tuned_model name, not a fine-tune ID"
|
30
|
-
end
|
31
|
-
|
32
|
-
@client.delete(path: "/models/#{fine_tuned_model}")
|
23
|
+
def list_events(id:)
|
24
|
+
@client.get(path: "/fine_tuning/jobs/#{id}/events")
|
33
25
|
end
|
34
26
|
end
|
35
27
|
end
|
data/lib/openai/http.rb
CHANGED
@@ -1,63 +1,61 @@
|
|
1
|
+
require "event_stream_parser"
|
2
|
+
|
1
3
|
module OpenAI
|
2
4
|
module HTTP
|
3
5
|
def get(path:)
|
4
|
-
|
6
|
+
parse_jsonl(conn.get(uri(path: path)) do |req|
|
5
7
|
req.headers = headers
|
6
8
|
end&.body)
|
7
9
|
end
|
8
10
|
|
9
11
|
def json_post(path:, parameters:)
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
parameters[:stream] = true # Necessary to tell OpenAI to stream.
|
14
|
-
elsif parameters[:stream]
|
15
|
-
raise ArgumentError, "The stream parameter must be a Proc or have a #call method"
|
16
|
-
end
|
17
|
-
|
18
|
-
req.headers = headers
|
19
|
-
req.body = parameters.to_json
|
20
|
-
end&.body)
|
12
|
+
conn.post(uri(path: path)) do |req|
|
13
|
+
configure_json_post_request(req, parameters)
|
14
|
+
end&.body
|
21
15
|
end
|
22
16
|
|
23
17
|
def multipart_post(path:, parameters: nil)
|
24
|
-
|
18
|
+
conn(multipart: true).post(uri(path: path)) do |req|
|
25
19
|
req.headers = headers.merge({ "Content-Type" => "multipart/form-data" })
|
26
20
|
req.body = multipart_parameters(parameters)
|
27
|
-
end&.body
|
21
|
+
end&.body
|
28
22
|
end
|
29
23
|
|
30
24
|
def delete(path:)
|
31
|
-
|
25
|
+
conn.delete(uri(path: path)) do |req|
|
32
26
|
req.headers = headers
|
33
|
-
end&.body
|
27
|
+
end&.body
|
34
28
|
end
|
35
29
|
|
36
30
|
private
|
37
31
|
|
38
|
-
def
|
39
|
-
return unless
|
32
|
+
def parse_jsonl(response)
|
33
|
+
return unless response
|
34
|
+
return response unless response.is_a?(String)
|
40
35
|
|
41
|
-
JSON.parse(string)
|
42
|
-
rescue JSON::ParserError
|
43
36
|
# Convert a multiline string of JSON objects to a JSON array.
|
44
|
-
|
37
|
+
response = response.gsub("}\n{", "},{").prepend("[").concat("]")
|
38
|
+
|
39
|
+
JSON.parse(response)
|
45
40
|
end
|
46
41
|
|
47
42
|
# Given a proc, returns an outer proc that can be used to iterate over a JSON stream of chunks.
|
48
43
|
# For each chunk, the inner user_proc is called giving it the JSON object. The JSON object could
|
49
44
|
# be a data object or an error object as described in the OpenAI API documentation.
|
50
45
|
#
|
51
|
-
# If the JSON object for a given data or error message is invalid, it is ignored.
|
52
|
-
#
|
53
46
|
# @param user_proc [Proc] The inner proc to call for each JSON object in the chunk.
|
54
47
|
# @return [Proc] An outer proc that iterates over a raw stream, converting it to JSON.
|
55
48
|
def to_json_stream(user_proc:)
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
49
|
+
parser = EventStreamParser::Parser.new
|
50
|
+
|
51
|
+
proc do |chunk, _bytes, env|
|
52
|
+
if env && env.status != 200
|
53
|
+
raise_error = Faraday::Response::RaiseError.new
|
54
|
+
raise_error.on_complete(env.merge(body: JSON.parse(chunk)))
|
55
|
+
end
|
56
|
+
|
57
|
+
parser.feed(chunk) do |_type, data|
|
58
|
+
user_proc.call(JSON.parse(data)) unless data == "[DONE]"
|
61
59
|
end
|
62
60
|
end
|
63
61
|
end
|
@@ -66,6 +64,8 @@ module OpenAI
|
|
66
64
|
Faraday.new do |f|
|
67
65
|
f.options[:timeout] = @request_timeout
|
68
66
|
f.request(:multipart) if multipart
|
67
|
+
f.response :raise_error
|
68
|
+
f.response :json
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
@@ -111,5 +111,19 @@ module OpenAI
|
|
111
111
|
Faraday::UploadIO.new(value, "", value.path)
|
112
112
|
end
|
113
113
|
end
|
114
|
+
|
115
|
+
def configure_json_post_request(req, parameters)
|
116
|
+
req_parameters = parameters.dup
|
117
|
+
|
118
|
+
if parameters[:stream].respond_to?(:call)
|
119
|
+
req.options.on_data = to_json_stream(user_proc: parameters[:stream])
|
120
|
+
req_parameters[:stream] = true # Necessary to tell OpenAI to stream.
|
121
|
+
elsif parameters[:stream]
|
122
|
+
raise ArgumentError, "The stream parameter must be a Proc or have a #call method"
|
123
|
+
end
|
124
|
+
|
125
|
+
req.headers = headers
|
126
|
+
req.body = req_parameters.to_json
|
127
|
+
end
|
114
128
|
end
|
115
129
|
end
|
data/lib/openai/version.rb
CHANGED
data/ruby-openai.gemspec
CHANGED
@@ -25,6 +25,7 @@ Gem::Specification.new do |spec|
|
|
25
25
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
26
26
|
spec.require_paths = ["lib"]
|
27
27
|
|
28
|
+
spec.add_dependency "event_stream_parser", ">= 0.3.0", "< 1.0.0"
|
28
29
|
spec.add_dependency "faraday", ">= 1"
|
29
30
|
spec.add_dependency "faraday-multipart", ">= 1"
|
30
31
|
end
|
metadata
CHANGED
@@ -1,15 +1,35 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-openai
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 6.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alex
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-11-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: event_stream_parser
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.3.0
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.0.0
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.3.0
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.0.0
|
13
33
|
- !ruby/object:Gem::Dependency
|
14
34
|
name: faraday
|
15
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,7 +58,7 @@ dependencies:
|
|
38
58
|
- - ">="
|
39
59
|
- !ruby/object:Gem::Version
|
40
60
|
version: '1'
|
41
|
-
description:
|
61
|
+
description:
|
42
62
|
email:
|
43
63
|
- alexrudall@users.noreply.github.com
|
44
64
|
executables: []
|
@@ -46,6 +66,10 @@ extensions: []
|
|
46
66
|
extra_rdoc_files: []
|
47
67
|
files:
|
48
68
|
- ".circleci/config.yml"
|
69
|
+
- ".devcontainer/Dockerfile"
|
70
|
+
- ".devcontainer/devcontainer.json"
|
71
|
+
- ".devcontainer/docker-compose.yml"
|
72
|
+
- ".github/FUNDING.yml"
|
49
73
|
- ".github/ISSUE_TEMPLATE/bug_report.md"
|
50
74
|
- ".github/ISSUE_TEMPLATE/feature_request.md"
|
51
75
|
- ".github/dependabot.yml"
|
@@ -83,7 +107,7 @@ metadata:
|
|
83
107
|
source_code_uri: https://github.com/alexrudall/ruby-openai
|
84
108
|
changelog_uri: https://github.com/alexrudall/ruby-openai/blob/main/CHANGELOG.md
|
85
109
|
rubygems_mfa_required: 'true'
|
86
|
-
post_install_message:
|
110
|
+
post_install_message:
|
87
111
|
rdoc_options: []
|
88
112
|
require_paths:
|
89
113
|
- lib
|
@@ -98,8 +122,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
98
122
|
- !ruby/object:Gem::Version
|
99
123
|
version: '0'
|
100
124
|
requirements: []
|
101
|
-
rubygems_version: 3.4.
|
102
|
-
signing_key:
|
125
|
+
rubygems_version: 3.4.10
|
126
|
+
signing_key:
|
103
127
|
specification_version: 4
|
104
128
|
summary: "OpenAI API + Ruby! \U0001F916❤️"
|
105
129
|
test_files: []
|