openai.rb 0.0.0 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/main.yml +27 -0
  3. data/.rubocop.yml +18 -0
  4. data/.ruby-version +1 -1
  5. data/Gemfile +9 -5
  6. data/Gemfile.lock +29 -24
  7. data/README.md +401 -0
  8. data/bin/console +9 -4
  9. data/lib/openai/api/cache.rb +137 -0
  10. data/lib/openai/api/client.rb +86 -0
  11. data/lib/openai/api/resource.rb +232 -0
  12. data/lib/openai/api/response.rb +384 -0
  13. data/lib/openai/api.rb +75 -0
  14. data/lib/openai/chat.rb +125 -0
  15. data/lib/openai/tokenizer.rb +50 -0
  16. data/lib/openai/util.rb +47 -0
  17. data/lib/openai/version.rb +1 -1
  18. data/lib/openai.rb +38 -357
  19. data/openai.gemspec +9 -3
  20. data/spec/data/sample_french.mp3 +0 -0
  21. data/spec/data/sample_image.png +0 -0
  22. data/spec/data/sample_image_mask.png +0 -0
  23. data/spec/shared/api_resource_context.rb +22 -0
  24. data/spec/spec_helper.rb +4 -0
  25. data/spec/unit/openai/api/audio_spec.rb +78 -0
  26. data/spec/unit/openai/api/cache_spec.rb +115 -0
  27. data/spec/unit/openai/api/chat_completions_spec.rb +130 -0
  28. data/spec/unit/openai/api/completions_spec.rb +125 -0
  29. data/spec/unit/openai/api/edits_spec.rb +40 -0
  30. data/spec/unit/openai/api/embeddings_spec.rb +45 -0
  31. data/spec/unit/openai/api/files_spec.rb +163 -0
  32. data/spec/unit/openai/api/fine_tunes_spec.rb +322 -0
  33. data/spec/unit/openai/api/images_spec.rb +137 -0
  34. data/spec/unit/openai/api/models_spec.rb +98 -0
  35. data/spec/unit/openai/api/moderations_spec.rb +63 -0
  36. data/spec/unit/openai/api/response_spec.rb +203 -0
  37. data/spec/unit/openai/chat_spec.rb +32 -0
  38. data/spec/unit/openai/tokenizer_spec.rb +45 -0
  39. data/spec/unit/openai_spec.rb +47 -736
  40. metadata +97 -7
  41. data/bin/codegen +0 -371
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e53fab536aad4674f7e0f4fee4dd5943ca9c89842a7c497e4385721d2f8b906c
4
- data.tar.gz: 876e5736c390a376f886a4dfc214645c94ccf7b54f067f0f969c6fd6890a28d6
3
+ metadata.gz: f049bfa7ff5419acf81a7cabc6e34b6bd223b8f9fcb634008544d93d87170c2f
4
+ data.tar.gz: d614701b82eaf3ec84e9ddb432505bbbd786f71d75378534b23400446ddb8e7b
5
5
  SHA512:
6
- metadata.gz: 162a9491e48177404cfcd7f0f962765c2adc5ae83dd913a5aa99b08c4cdcfa9a4ceb6975ff7dc52241b7c2874d67888acc4bd7750ca50e10325f981be94e7787
7
- data.tar.gz: 0ea4ed08887bf15d62db2a8393e8268cd5002011957c5268b93be44fac1e45c8fbd067ab0ef3493c5e9e22e3fac9e36b00b53980dd84975fe0dee6065556ca25
6
+ metadata.gz: c321d0184079826648569ab13b04675d9cbfb04027fed85b191d462c6585cc375d9144dede8ecf6d9995e48be935bf6879dba969e17492cb9c4ffe100f468fea
7
+ data.tar.gz: 3fd0d70f0007e3900e6df1f39ef18dcbd618b7e3384de229b50936924bb4bf80e79d19bd7a531be6caade2b915c03581cccabc32f01b5921c79bd88e224c27a0
@@ -0,0 +1,27 @@
1
+ name: Ruby Gem CI
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ test:
7
+ runs-on: ubuntu-latest
8
+ strategy:
9
+ matrix:
10
+ http_version: ['~> 4.4', '~> 5.1']
11
+ ruby_version: ['2.7.8']
12
+
13
+ steps:
14
+ - uses: actions/checkout@v2
15
+ - name: Update .ruby-version
16
+ run: echo "${{ matrix.ruby_version }}" > .ruby-version
17
+ - name: Set up Ruby
18
+ uses: ruby/setup-ruby@v1
19
+ with:
20
+ ruby-version: ${{ matrix.ruby_version }}
21
+ bundler-cache: true
22
+ - name: Install dependencies
23
+ run: |
24
+ echo "gem 'http', '${{ matrix.http_version }}'" >> Gemfile.local
25
+ bundle install
26
+ - name: Run tests
27
+ run: bundle exec rspec
data/.rubocop.yml ADDED
@@ -0,0 +1,18 @@
1
+ Metrics/AbcSize:
2
+ Enabled: false
3
+
4
+ Metrics/BlockLength:
5
+ Enabled: false
6
+
7
+ Metrics/MethodLength:
8
+ Enabled: false
9
+
10
+ Style/Documentation:
11
+ Enabled: false
12
+
13
+ Layout/LineLength:
14
+ Enabled: false
15
+
16
+ Style/FrozenStringLiteralComment:
17
+ SafeAutoCorrect: true
18
+ Enabled: true
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.6.9
1
+ 2.7.7
data/Gemfile CHANGED
@@ -11,13 +11,17 @@ group :test do
11
11
  end
12
12
 
13
13
  group :lint do
14
- gem 'rubocop'
15
- gem 'rubocop-rspec'
14
+ gem 'rubocop', '~> 1.31.1'
15
+ gem 'rubocop-rspec', '~> 2.11.1'
16
16
  end
17
17
 
18
18
  gem 'pry', '~> 0.13.1'
19
- gem 'pry-byebug', '~> 3.9'
19
+ gem 'pry-byebug', '3.9.0'
20
20
 
21
- gem "dotenv", "~> 2.8"
21
+ gem 'dotenv', '~> 2.8'
22
22
 
23
- gem "slop", "~> 4.10"
23
+ gem 'slop', '~> 4.10'
24
+
25
+ gem 'http', '~> 4.4' # For testing the older version of HTTP.rb
26
+
27
+ gem 'rb_sys', '~> 0.9.70'
data/Gemfile.lock CHANGED
@@ -1,10 +1,14 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- openai.rb (0.0.0)
4
+ openai.rb (0.0.3)
5
+ abstract_type (~> 0.0.7)
5
6
  anima (~> 0.3)
6
7
  concord (~> 0.1)
7
- http (~> 5.1)
8
+ http (>= 4.4, < 6.0)
9
+ ice_nine (~> 0.11.x)
10
+ memoizable (~> 0.4.2)
11
+ tiktoken_ruby (~> 0.0.3)
8
12
 
9
13
  GEM
10
14
  remote: https://rubygems.org/
@@ -13,7 +17,7 @@ GEM
13
17
  adamantium (0.2.0)
14
18
  ice_nine (~> 0.11.0)
15
19
  memoizable (~> 0.4.0)
16
- addressable (2.8.1)
20
+ addressable (2.8.2)
17
21
  public_suffix (>= 2.0.2, < 6.0)
18
22
  anima (0.3.2)
19
23
  abstract_type (~> 0.0.7)
@@ -34,24 +38,23 @@ GEM
34
38
  ffi-compiler (1.0.1)
35
39
  ffi (>= 1.0.0)
36
40
  rake
37
- http (5.1.1)
38
- addressable (~> 2.8)
41
+ http (4.4.1)
42
+ addressable (~> 2.3)
39
43
  http-cookie (~> 1.0)
40
44
  http-form_data (~> 2.2)
41
- llhttp-ffi (~> 0.4.0)
45
+ http-parser (~> 1.2.0)
42
46
  http-cookie (1.0.5)
43
47
  domain_name (~> 0.5)
44
48
  http-form_data (2.3.0)
49
+ http-parser (1.2.3)
50
+ ffi-compiler (>= 1.0, < 2.0)
45
51
  ice_nine (0.11.2)
46
52
  json (2.6.3)
47
- llhttp-ffi (0.4.0)
48
- ffi-compiler (~> 1.0)
49
- rake (~> 13.0)
50
53
  memoizable (0.4.2)
51
54
  thread_safe (~> 0.3, >= 0.3.1)
52
55
  method_source (1.0.0)
53
56
  parallel (1.22.1)
54
- parser (3.2.1.1)
57
+ parser (3.2.2.0)
55
58
  ast (~> 2.4.1)
56
59
  pry (0.13.1)
57
60
  coderay (~> 1.1)
@@ -62,6 +65,7 @@ GEM
62
65
  public_suffix (5.0.1)
63
66
  rainbow (3.1.1)
64
67
  rake (13.0.6)
68
+ rb_sys (0.9.70)
65
69
  regexp_parser (2.7.0)
66
70
  rexml (3.2.5)
67
71
  rspec (3.12.0)
@@ -73,30 +77,28 @@ GEM
73
77
  rspec-expectations (3.12.2)
74
78
  diff-lcs (>= 1.2.0, < 2.0)
75
79
  rspec-support (~> 3.12.0)
76
- rspec-mocks (3.12.4)
80
+ rspec-mocks (3.12.5)
77
81
  diff-lcs (>= 1.2.0, < 2.0)
78
82
  rspec-support (~> 3.12.0)
79
83
  rspec-support (3.12.0)
80
- rubocop (1.48.1)
84
+ rubocop (1.31.2)
81
85
  json (~> 2.3)
82
86
  parallel (~> 1.10)
83
- parser (>= 3.2.0.0)
87
+ parser (>= 3.1.0.0)
84
88
  rainbow (>= 2.2.2, < 4.0)
85
89
  regexp_parser (>= 1.8, < 3.0)
86
90
  rexml (>= 3.2.5, < 4.0)
87
- rubocop-ast (>= 1.26.0, < 2.0)
91
+ rubocop-ast (>= 1.18.0, < 2.0)
88
92
  ruby-progressbar (~> 1.7)
89
- unicode-display_width (>= 2.4.0, < 3.0)
93
+ unicode-display_width (>= 1.4.0, < 3.0)
90
94
  rubocop-ast (1.28.0)
91
95
  parser (>= 3.2.1.0)
92
- rubocop-capybara (2.17.1)
93
- rubocop (~> 1.41)
94
- rubocop-rspec (2.19.0)
95
- rubocop (~> 1.33)
96
- rubocop-capybara (~> 2.17)
96
+ rubocop-rspec (2.11.1)
97
+ rubocop (~> 1.19)
97
98
  ruby-progressbar (1.13.0)
98
99
  slop (4.10.1)
99
100
  thread_safe (0.3.6)
101
+ tiktoken_ruby (0.0.4)
100
102
  unf (0.1.4)
101
103
  unf_ext
102
104
  unf_ext (0.0.8.2)
@@ -104,19 +106,22 @@ GEM
104
106
 
105
107
  PLATFORMS
106
108
  arm64-darwin-21
109
+ ruby
107
110
 
108
111
  DEPENDENCIES
109
112
  dotenv (~> 2.8)
113
+ http (~> 4.4)
110
114
  openai.rb!
111
115
  pry (~> 0.13.1)
112
- pry-byebug (~> 3.9)
116
+ pry-byebug (= 3.9.0)
117
+ rb_sys (~> 0.9.70)
113
118
  rspec (~> 3.12)
114
- rubocop
115
- rubocop-rspec
119
+ rubocop (~> 1.31.1)
120
+ rubocop-rspec (~> 2.11.1)
116
121
  slop (~> 4.10)
117
122
 
118
123
  RUBY VERSION
119
- ruby 2.6.9p207
124
+ ruby 2.7.7p221
120
125
 
121
126
  BUNDLED WITH
122
127
  2.3.9
data/README.md ADDED
@@ -0,0 +1,401 @@
1
+ # OpenAI.rb
2
+
3
+ A comprehensive (as of March 25th, 2023) OpenAI API wrapper with built-in support for:
4
+
5
+ * caching
6
+ * tokenization
7
+ * response streaming
8
+ * a simple chainable abstraction for chats
9
+
10
+ ## Install and Setup
11
+
12
+ To install, you should be able to do:
13
+
14
+ ```sh
15
+ $ gem install openai.rb
16
+ ```
17
+
18
+ Usage:
19
+
20
+ ```ruby
21
+ require 'openai'
22
+
23
+ openai = OpenAI.create(ENV.fetch('OPENAI_API_KEY'))
24
+ openai.api.chat_completions.create(...)
25
+ openai.api.embeddings.create(...)
26
+ openai.api.models.list
27
+ # etc
28
+ ```
29
+
30
+ ### Caching
31
+
32
+ Caching for requests is built-in. The supported caching strategy writes response files in a directory you
33
+ specify (I chose to write as separate files since I often want to dig around and see the raw data I'm getting
34
+ back).
35
+
36
+ To enable caching:
37
+
38
+ ```ruby
39
+ require 'openai'
40
+
41
+ # This directory should already exist
42
+ cache_dir = Pathname.new('~/.cache/openai')
43
+
44
+ openai = OpenAI.create(ENV.fetch('OPENAI_API_KEY'), cache: cache_dir)
45
+
46
+ # Will hit the API:
47
+ openai.api.completions.create(model: 'text-davinci-002', prompt: 'Say hi')
48
+ # Will reuse the cached response:
49
+ openai.api.completions.create(model: 'text-davinci-002', prompt: 'Say hi')
50
+ ```
51
+
52
+ NOTE: Delete requests are not cached
53
+
54
+ ### Tokens
55
+
56
+ ```ruby
57
+ # Get encoder for a model and encode
58
+ openai.tokens.for_model('gpt-4').encode('Hello world')
59
+
60
+ # Get encoder by name
61
+ openai.tokens.get('cl100k_base').encode('Hello world')
62
+
63
+ # Get number of tokens
64
+ openai.tokens.for_model('gpt-4').num_tokens('Hello, world!') # => 4
65
+ ```
66
+
67
+ ### Chat Abstraction
68
+
69
+ You can use `openai.chat` in order to create a simple chainable chat interface with a model:
70
+
71
+ ```ruby
72
+ openai = OpenAI.create(ENV.fetch('OPENAI_API_KEY'))
73
+
74
+ chat = openai.chat(model: 'gpt-3.5-turbo')
75
+
76
+ chat =
77
+ chat
78
+ .system('You are a chatbot that talks and acts like scooby doo.')
79
+ .user('Hi how are you doing today?')
80
+ .submit # API call
81
+ .user('Nice. What kind of snacks do you like?')
82
+ .submit # API call
83
+
84
+ puts chat.to_log_format
85
+ ```
86
+
87
+ Which results in this output:
88
+
89
+ > SYSTEM: You are a chatbot that talks and acts like scooby doo.
90
+ >
91
+ > USER: Hi how are you doing today?
92
+ >
93
+ > ASSISTANT: Ruh-roh! Hello there, buddy! Scooby-Dooby-Doo is doing great! How about you, pal?
94
+ >
95
+ > USER: Nice. What kind of snacks do you like?
96
+ >
97
+ > ASSISTANT: Ruh-roh! Scooby-Dooby-Doo loves all kinds of snacks, especially Scooby Snacks! They are my favorite! But I also love bones, pizza, hamburgers, and any kind of food that's tasty and yummy. How about you, buddy? Do you have a favorite snack?
98
+
99
+ ## API
100
+
101
+ ### Audio
102
+
103
+ Transcribing audio:
104
+
105
+ ```ruby
106
+ transcription = openai.api.audio.transcribe(
107
+ file: '/path/to/sample.mp3',
108
+ model: 'model-id'
109
+ )
110
+
111
+ transcription.text # => "Imagine the wildest idea that you've ever had..."
112
+ ```
113
+
114
+ Translating audio:
115
+
116
+ ```ruby
117
+ translation = openai.api.audio.translate(
118
+ file: '/path/to/french/sample.mp3',
119
+ model: 'model-id',
120
+ )
121
+
122
+ translation.text # => "Hello, my name is Wolfgang and I come from Germany. Where are you heading today?"
123
+ ```
124
+
125
+ ### Chat completions
126
+
127
+ Generating a chat completion:
128
+
129
+ ```ruby
130
+ completion = openai.api.chat_completions.create(
131
+ model: 'gpt-3.5-turbo',
132
+ messages: [
133
+ { role: "user", content: "Hello" }
134
+ ]
135
+ )
136
+
137
+ completion.choices.first.message.content # => "\n\nHello there, how may I assist you today?"
138
+ ```
139
+
140
+ Streaming chat completion responses:
141
+
142
+ ```ruby
143
+ completion = openai.api.chat_completions.create(
144
+ model: 'gpt-3.5-turbo',
145
+ messages: [{ role: "user", content: "Hello" }],
146
+ stream: true
147
+ ) do |completion|
148
+ print completion.choices.first.delta.content
149
+ end
150
+
151
+ # >> "\n\nHello there, how may I assist you today?"
152
+ ```
153
+
154
+ ### Completions
155
+
156
+ Generating a completion:
157
+
158
+ ```ruby
159
+ completion = openai.api.completions.create(
160
+ model: 'text-davinci-002',
161
+ prompt: 'Hello, world!'
162
+ )
163
+
164
+ completion.id # => "cmpl-uqkvlQyYK7bGYrRHQ0eXlWi7"
165
+ completion.model # => "text-davinci-003"
166
+ completion.choices.first.text # => "\n\nThis is indeed a test"
167
+ ```
168
+
169
+ Streaming responses:
170
+
171
+ ```ruby
172
+ completion = openai.api.completions.create(
173
+ model: 'text-davinci-002',
174
+ prompt: 'Say hello world',
175
+ stream: true
176
+ ) do |completion|
177
+ puts completion.choices.first.text
178
+ end
179
+
180
+ # >> "He"
181
+ # >> "llo,"
182
+ # >> " world"
183
+ # >> "!"
184
+ ```
185
+
186
+ ### Edits
187
+
188
+ Creating an edit:
189
+
190
+ ```ruby
191
+ edit = openai.api.edits.create(
192
+ model: 'text-davinci-002',
193
+ input: "What day of the wek is it?",
194
+ instruction: "Fix the spelling mistake"
195
+ )
196
+
197
+ edit.object # => "edit"
198
+ edit.choices.first.text # => "What day of the week is it?"
199
+ ```
200
+
201
+ ### Embeddings
202
+
203
+ Creating an embedding vector for a given input text:
204
+
205
+ ```ruby
206
+ embedding = openai.api.embeddings.create(
207
+ model: 'text-embedding-ada-002',
208
+ input: 'Hello, world!'
209
+ )
210
+
211
+ embedding.object # => 'list'
212
+ embedding.data.first.object # => 'embedding'
213
+ embedding.data.first.embedding.size # => 1536
214
+ ```
215
+
216
+ ### Files
217
+
218
+ Upload a file:
219
+
220
+ ```ruby
221
+
222
+ file = openai.api.files.create(
223
+ file: '/path/to/file.jsonl',
224
+ purpose: 'fine-tune'
225
+ )
226
+
227
+ file.id # => 'file-XjGxS3KTG0uNmNOK362iJua3'
228
+ file.filename # => 'sample.jsonl'
229
+ file.purpose # => 'fine-tune'
230
+ file.deleted? # => nil
231
+ ```
232
+
233
+ Get a list of files:
234
+
235
+ ```ruby
236
+
237
+ files = openai.api.files.list
238
+
239
+ files.data.size # => 2
240
+ files.data.first.filename # => 'train.jsonl'
241
+ ```
242
+
243
+ Fetch a specific file’s information:
244
+
245
+ ```ruby
246
+
247
+ file = openai.api.files.fetch('file-XjGxS3KTG0uNmNOK362iJua3')
248
+
249
+ file.filename # => 'mydata.jsonl'
250
+ file.bytes # => 140
251
+ file.created_at # => 1613779657
252
+ file.purpose # => 'fine-tune'
253
+ file.object # => 'file'
254
+ ```
255
+
256
+ Get the contents of a file:
257
+
258
+ ```ruby
259
+
260
+ response = openai.api.files.get_content('file-XjGxS3KTG0uNmNOK362iJua3')
261
+
262
+ puts response # => (whatever you uploaded)
263
+ ```
264
+
265
+ Delete a file:
266
+
267
+ ```ruby
268
+
269
+ file = openai.api.files.delete('file-XjGxS3KTG0uNmNOK362iJua3')
270
+
271
+ file.deleted? # => true
272
+ ```
273
+
274
+ ### Fine-tunes
275
+
276
+ Creating a fine tune:
277
+
278
+ ```ruby
279
+ fine_tune = openai.api.fine_tunes.create(training_file: 'file-XGinujblHPwGLSztz8cPS8XY')
280
+
281
+ details.id # => "ft-AF1WoRqd3aJAHsqc9NY7iL8F"
282
+ ```
283
+
284
+ Listing fine tunes:
285
+
286
+ ```ruby
287
+ fine_tunes = openai.api.fine_tunes.list
288
+
289
+ fine_tunes.data.first.id # => "ft-AF1WoRqd3aJAHsqc9NY7iL8F"
290
+ fine_tunes.data.first.status # => "pending"
291
+ ```
292
+
293
+
294
+ Fetching a fine tune:
295
+
296
+ ```ruby
297
+ fine_tune = openai.api.fine_tunes.fetch('ft-AF1WoRqd3aJAHsqc9NY7iL8F')
298
+ fine_tune.id # => "ft-AF1WoRqd3aJAHsqc9NY7iL8F"
299
+ ```
300
+
301
+ Canceling a fine tune:
302
+
303
+ ```ruby
304
+
305
+ # Canceling a fine tune
306
+ fine_tune = openai.api.fine_tunes.cancel('ft-xhrpBbvVUzYGo8oUO1FY4nI7')
307
+ fine_tune.id # => "ft-xhrpBbvVUzYGo8oUO1FY4nI7"
308
+ fine_tune.status # => "cancelled"
309
+ ```
310
+
311
+ Listing fine tune events:
312
+
313
+ ```ruby
314
+ events = openai.api.fine_tunes.list_events('fine-tune-id')
315
+ ```
316
+
317
+ ### Images
318
+
319
+ #### Generating Images
320
+
321
+ Create an image with the specified prompt and size:
322
+
323
+ ```ruby
324
+ images = openai.api.images.create(prompt: 'a bird in the forest', size: '512x512')
325
+
326
+ images.data.first.url # => "https://example.com/image1.png"
327
+ ```
328
+
329
+ #### Editing Images
330
+
331
+ Edit an image with the specified parameters:
332
+
333
+ ```ruby
334
+ response = openai.api.images.edit(
335
+ image: '/path/to/some_rgba.png',
336
+ mask: '/path/to/some_rgba_mask.png',
337
+ prompt: 'Draw a red hat on the person in the image',
338
+ n: 1,
339
+ size: '512x512',
340
+ response_format: 'url',
341
+ user: 'user-123'
342
+ )
343
+
344
+ response.created # => 1589478378
345
+ response.data.first.url # => "https://..."
346
+ ```
347
+
348
+ #### Creating Image Variations
349
+
350
+ Create image variations of the specified image with the specified parameters:
351
+
352
+ ```ruby
353
+ image_variations = openai.api.images.create_variation(
354
+ image: '/path/to/some_rgba.png',
355
+ n: 2,
356
+ size: '512x512',
357
+ response_format: 'url',
358
+ user: 'user123'
359
+ )
360
+
361
+ image_variations.created # => 1589478378
362
+ image_variations.data.map(&:url) # => ["https://...", "https://..."]
363
+ ```
364
+
365
+ ### Models
366
+
367
+ Listing all models:
368
+
369
+ ```ruby
370
+ models = api.models.list
371
+
372
+ models.data.first.id # => "model-id-0"
373
+ models.data.size # => 3
374
+ ```
375
+
376
+ Retrieving a model:
377
+
378
+ ```ruby
379
+ model = api.models.fetch('text-davinci-002')
380
+
381
+ model.id # => "text-davinci-002"
382
+ model.object # => "model"
383
+ model.owned_by # => "openai"
384
+ model.permission # => ["query", "completions", "models:read", "models:write", "engine:read", "engine:write"]
385
+ ```
386
+
387
+ ### Moderations
388
+
389
+ Moderate text:
390
+
391
+ ```ruby
392
+ moderation = openai.api.moderations.create(
393
+ input: 'This is a test',
394
+ model: 'text-moderation-001'
395
+ )
396
+
397
+ moderation.id # => "modr-5MWoLO"
398
+ moderation.model # => "text-moderation-001"
399
+ moderation.results.first.categories.hate # => false
400
+ moderation.results.first.categories.hate_threatening # => true
401
+ ```
data/bin/console CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'bundler/setup'
4
5
  require 'openai'
@@ -8,9 +9,13 @@ require 'pry-byebug'
8
9
 
9
10
  Dotenv.load
10
11
 
11
- def start_repl
12
- api = OpenAI.new(ENV.fetch('OPENAI_API_KEY'))
13
- binding.pry
14
- end
12
+ cache_dir = Pathname.new(__dir__).parent.join('tmp/console_cache')
13
+ cache_dir.mkpath unless cache_dir.exist?
14
+ openai = OpenAI.create(
15
+ ENV.fetch('OPENAI_API_KEY'),
16
+ cache: cache_dir
17
+ )
18
+
19
+ Pry.start_without_pry_byebug(binding, quiet: true)
15
20
 
16
21
  start_repl