openai.rb 0.0.0 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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