omniai-openai 1.3.1 → 1.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 32b555cd7f80abb2cc11a12986a0a8df15e5c1d9b6d31113f5e00b47174f4ec6
4
- data.tar.gz: 81046a31442f6f2b1a1eb5d37723deefbb82cf7c145907ae0bb72db738e09080
3
+ metadata.gz: c5f48cc11134ffb023a4d1797a637ee1a0a6ae0365da799df07c484f177a58cb
4
+ data.tar.gz: 971a2c0524376bd64cf4c1e04b82ab0373b20314d11a06eb0ebc7113f6b9515f
5
5
  SHA512:
6
- metadata.gz: '0939f67a3bc54221fc1141b00ab8eb1c38323178da2c3c78057cd25a288df776397eb204c18f5425005a92f05556a67b28b902b6520716c359b7901a70d7e183'
7
- data.tar.gz: 7611023c850321bec21b71dfb626b5c308905e55a1485d5c965d1e31f2e9ced8fa09929ada98eff681a933499e5735b88243c404cf7452c2fbf0aab3fd515606
6
+ metadata.gz: c3765f6900534a23d7dc6033f0dc73dc31845494b938e33d345374e4e76ba16e300083cf1c2bedfc82ccc727a29636327092ea86b05f265eae40881de43fe0e8
7
+ data.tar.gz: b37e93448e1b3314724af029fcdca1f472b6a4e55b027a864079881d5139211b4f8001c0b805479af24ff6f69e586fd919d78bf10843d7de046ca525805e75e3
data/README.md CHANGED
@@ -268,8 +268,17 @@ client.files.all
268
268
 
269
269
  ### Uploading a File
270
270
 
271
+ #### Using a File
272
+
273
+ ```ruby
274
+ file = client.files.build(io: File.open('demo.pdf', 'wb'))
275
+ file.save!
276
+ ```
277
+
278
+ #### Using a Path
279
+
271
280
  ```ruby
272
- file = client.files.build(io: File.open('...', 'wb'))
281
+ file = client.files.build(io: 'demo.pdf'))
273
282
  file.save!
274
283
  ```
275
284
 
@@ -428,6 +437,15 @@ run.metadata = { user: 'Ringo' }
428
437
  run.save!
429
438
  ```
430
439
 
440
+ #### Polling a Run
441
+
442
+ ```ruby
443
+ run.terminated? # false
444
+ run.poll!
445
+ run.terminated? # true
446
+ run.status # 'cancelled' / 'failed' / 'completed' / 'expired'
447
+ ```
448
+
431
449
  #### Cancelling a Run
432
450
 
433
451
  ```ruby
@@ -49,7 +49,7 @@ module OmniAI
49
49
  client: Client.new,
50
50
  id: nil,
51
51
  name: nil,
52
- model: nil,
52
+ model: OmniAI::Chat::DEFAULT_MODEL,
53
53
  description: nil,
54
54
  instructions: nil,
55
55
  metadata: {},
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OmniAI
4
+ module OpenAI
5
+ class Thread
6
+ # An OpenAI content w/ annotations.
7
+ class Annotation
8
+ # @!attribute [rw] data
9
+ # @return [Hash, nil]
10
+ attr_accessor :data
11
+
12
+ # @param data [Hash] required
13
+ # @param client [OmniAI::OpenAI::Client] optional
14
+ def initialize(data:, client: Client.new)
15
+ @data = data
16
+ @client = client
17
+ end
18
+
19
+ # @return [String] "file_citation" or "file_path"
20
+ def type
21
+ @data['type']
22
+ end
23
+
24
+ # @return [String]
25
+ def text
26
+ @data['text']
27
+ end
28
+
29
+ # @return [Integer]
30
+ def start_index
31
+ @data['start_index']
32
+ end
33
+
34
+ # @return [Integer]
35
+ def end_index
36
+ @data['end_index']
37
+ end
38
+
39
+ # @return [Range<Integer>]
40
+ def range
41
+ start_index..end_index
42
+ end
43
+
44
+ # @return [String]
45
+ def file_id
46
+ @file_id ||= (@data['file_citation'] || @data['file_path'])['file_id']
47
+ end
48
+
49
+ # Present if type is "file_citation" or "file_path".
50
+ #
51
+ # @return [OmniAI::OpenAI::File, nil]
52
+ def file!
53
+ @file ||= @client.files.find(id: file_id)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OmniAI
4
+ module OpenAI
5
+ class Thread
6
+ # An OpenAI attachment.
7
+ class Attachment
8
+ # @!attribute [rw] data
9
+ # @return [Hash, nil]
10
+ attr_accessor :data
11
+
12
+ # @param data [Array]
13
+ # @param client [OmniAI::OpenAI::Client]
14
+ #
15
+ # @return [Array<OmniAI::OpenAI::Thread::Content>, String, nil]
16
+ def self.for(data:, client: Client.new)
17
+ return data unless data.is_a?(Enumerable)
18
+
19
+ data.map { |attachment| new(data: attachment, client:) }
20
+ end
21
+
22
+ # @param data [Hash]
23
+ # @param client [OmniAI::OpenAI::Client]
24
+ def initialize(data:, client: Client.new)
25
+ @data = data
26
+ @client = client
27
+ end
28
+
29
+ # @return [String] e.g. "text"
30
+ def file_id
31
+ @file_id ||= @data['file_id']
32
+ end
33
+
34
+ # @return [Array<Hash>]
35
+ def tools
36
+ @tools ||= @data['tools']
37
+ end
38
+
39
+ # @return [OmniAI::OpenAI::File]
40
+ def file!
41
+ @file ||= @client.files.find(id: file_id)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OmniAI
4
+ module OpenAI
5
+ class Thread
6
+ # An OpenAI content w/ annotations.
7
+ class Content
8
+ module Type
9
+ TEXT = 'text'
10
+ end
11
+
12
+ # @param data [Array]
13
+ # @param client [OmniAI::OpenAI::Client]
14
+ #
15
+ # @return [Array<OmniAI::OpenAI::Thread::Content>, String, nil]
16
+ def self.for(data:, client: Client.new)
17
+ return data unless data.is_a?(Enumerable)
18
+
19
+ data.map { |attachment| new(data: attachment, client:) }
20
+ end
21
+
22
+ # @!attribute [rw] data
23
+ # @return [Hash, nil]
24
+ attr_accessor :data
25
+
26
+ # @param data [Hash]
27
+ def initialize(data:, client:)
28
+ @data = data
29
+ @client = client
30
+ end
31
+
32
+ # @return [String] e.g. "text"
33
+ def type
34
+ @type ||= @data['type']
35
+ end
36
+
37
+ # @return [Boolean]
38
+ def text?
39
+ type.eql?(Type::TEXT)
40
+ end
41
+
42
+ # @return [OmniAI::OpenAI::Thread::Text]
43
+ def text
44
+ @text ||= Text.new(data: @data['text'], client: @client) if @data['text']
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -168,8 +168,8 @@ module OmniAI
168
168
  thread_id: data['thread_id'],
169
169
  run_id: data['run_id'],
170
170
  role: data['role'],
171
- content: data['content'],
172
- attachments: data['attachments'],
171
+ content: Content.for(data: data['content'], client:),
172
+ attachments: Attachment.for(data: data['attachments'], client:),
173
173
  metadata: data['metadata']
174
174
  )
175
175
  end
@@ -181,9 +181,9 @@ module OmniAI
181
181
  @assistant_id = data['assistant_id']
182
182
  @thread_id = data['thread_id']
183
183
  @run_id = data['run_id']
184
- @role = data['role']
185
- @content = data['content']
186
- @attachments = data['attachments']
184
+ @role = data['role']
185
+ @content = Content.for(data: data['content'], client: @client)
186
+ @attachments = Attachment.for(data: data['content'], client: @client)
187
187
  @metadata = data['metadata']
188
188
  end
189
189
 
@@ -14,7 +14,7 @@ module OmniAI
14
14
 
15
15
  # @param limit [Integer] optional
16
16
  # @return [Array<OmniAI::Thread::Message>]
17
- def all(limit:)
17
+ def all(limit: nil)
18
18
  Message.all(thread_id: @thread.id, limit:, client: @client)
19
19
  end
20
20
 
@@ -5,6 +5,20 @@ module OmniAI
5
5
  class Thread
6
6
  # An OpenAI run within a thread.
7
7
  class Run
8
+ module Status
9
+ CANCELLED = 'cancelled'
10
+ FAILED = 'failed'
11
+ COMPLETED = 'completed'
12
+ EXPIRED = 'expired'
13
+ end
14
+
15
+ TERMINATED_STATUSES = [
16
+ Status::CANCELLED,
17
+ Status::FAILED,
18
+ Status::COMPLETED,
19
+ Status::EXPIRED,
20
+ ].freeze
21
+
8
22
  # @!attribute [rw] id
9
23
  # @return [String, nil]
10
24
  attr_accessor :id
@@ -143,6 +157,22 @@ module OmniAI
143
157
  self
144
158
  end
145
159
 
160
+ # @raise [HTTPError]
161
+ # @return [OmniAI::OpenAI::Thread]
162
+ def reload!
163
+ raise Error, 'unable to fetch! without an ID' unless @id
164
+
165
+ response = @client.connection
166
+ .accept(:json)
167
+ .headers(HEADERS)
168
+ .get(path)
169
+
170
+ raise HTTPError, response.flush unless response.status.ok?
171
+
172
+ parse(data: response.parse)
173
+ self
174
+ end
175
+
146
176
  # @raise [OmniAI::Error]
147
177
  # @return [OmniAI::OpenAI::Thread]
148
178
  def cancel!
@@ -153,6 +183,23 @@ module OmniAI
153
183
  self
154
184
  end
155
185
 
186
+ # @param interval [Integer, Float, nil] optional (seconds)
187
+ #
188
+ # @return [OmniAI::OpenAI::Thread::Run]
189
+ def poll!(delay: 2)
190
+ loop do
191
+ reload!
192
+ break if terminated?
193
+
194
+ sleep(delay) if delay
195
+ end
196
+ end
197
+
198
+ # @return [Boolean]
199
+ def terminated?
200
+ TERMINATED_STATUSES.include?(@status)
201
+ end
202
+
156
203
  private
157
204
 
158
205
  class << self
@@ -14,7 +14,7 @@ module OmniAI
14
14
 
15
15
  # @param limit [Integer] optional
16
16
  # @return [Array<OmniAI::Thread::Message>]
17
- def all(limit:)
17
+ def all(limit: nil)
18
18
  Run.all(thread_id: @thread.id, limit:, client: @client)
19
19
  end
20
20
 
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OmniAI
4
+ module OpenAI
5
+ class Thread
6
+ # An OpenAI text w/ annotations.
7
+ class Text
8
+ # @!attribute [rw] data
9
+ # @return [Hash, nil]
10
+ attr_accessor :data
11
+
12
+ # @param data [Hash]
13
+ # @param client [OmniAI::OpenAI::Client]
14
+ def initialize(data:, client:)
15
+ @data = data
16
+ @client = client
17
+ end
18
+
19
+ # @return [String]
20
+ def annotate!
21
+ text = value
22
+
23
+ annotations.each do |annotation|
24
+ file = annotation.file!
25
+ text = text.gsub(annotation.text, "[#{file.filename}:#{annotation.range}]")
26
+ end
27
+
28
+ text
29
+ end
30
+
31
+ # @return [String] e.g. "text"
32
+ def type
33
+ @data['type']
34
+ end
35
+
36
+ # @return [String]
37
+ def value
38
+ @data['value']
39
+ end
40
+
41
+ # @return [Array<OmniAI::OpenAI::Thread::Annotation>]
42
+ def annotations
43
+ @annotations ||= @data['annotations'].map { |data| Annotation.new(data:, client: @client) }
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module OmniAI
4
4
  module OpenAI
5
- VERSION = '1.3.1'
5
+ VERSION = '1.3.3'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omniai-openai
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.1
4
+ version: 1.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin Sylvestre
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-06-24 00:00:00.000000000 Z
11
+ date: 2024-06-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: event_stream_parser
@@ -71,10 +71,14 @@ files:
71
71
  - lib/omniai/openai/files.rb
72
72
  - lib/omniai/openai/speak.rb
73
73
  - lib/omniai/openai/thread.rb
74
+ - lib/omniai/openai/thread/annotation.rb
75
+ - lib/omniai/openai/thread/attachment.rb
76
+ - lib/omniai/openai/thread/content.rb
74
77
  - lib/omniai/openai/thread/message.rb
75
78
  - lib/omniai/openai/thread/messages.rb
76
79
  - lib/omniai/openai/thread/run.rb
77
80
  - lib/omniai/openai/thread/runs.rb
81
+ - lib/omniai/openai/thread/text.rb
78
82
  - lib/omniai/openai/threads.rb
79
83
  - lib/omniai/openai/tool.rb
80
84
  - lib/omniai/openai/transcribe.rb