ox-ai-workers 0.2.5 → 0.3.1
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 +4 -4
- data/CHANGELOG.md +11 -0
- data/README.md +15 -6
- data/exe/oxaiworkers +1 -1
- data/exe/start +3 -3
- data/lib/ox-ai-workers.rb +28 -34
- data/lib/oxaiworkers/assistant/sysop.rb +5 -1
- data/lib/oxaiworkers/compatibility.rb +2 -0
- data/lib/oxaiworkers/delayed_request.rb +95 -93
- data/lib/oxaiworkers/iterator.rb +154 -159
- data/lib/oxaiworkers/load_i18n.rb +4 -0
- data/lib/oxaiworkers/module_request.rb +62 -62
- data/lib/oxaiworkers/present_compat.rb +31 -27
- data/lib/oxaiworkers/request.rb +15 -13
- data/lib/oxaiworkers/state_batch.rb +50 -46
- data/lib/oxaiworkers/state_helper.rb +8 -4
- data/lib/oxaiworkers/state_tools.rb +46 -43
- data/lib/oxaiworkers/tool/eval.rb +20 -18
- data/lib/oxaiworkers/version.rb +1 -1
- data/locales/en.assistant.yml +5 -0
- data/locales/{en.system.yml → en.iterator.yml} +0 -11
- data/locales/en.tool.yml +10 -0
- data/locales/ru.assistant.yml +5 -0
- data/locales/{ru.system.yml → ru.iterator.yml} +0 -11
- data/locales/ru.tool.yml +10 -0
- data/template/my_assistant.rb +6 -1
- data/template/start +10 -4
- metadata +8 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 22ef23635cb8c4a085d92a6891d5a7b42ea4a2421c31566b2e0a0c64019ffde4
|
4
|
+
data.tar.gz: d3ee3406e6408da1f4abf1327e0b327cfdc9d70cab53368167a0074e995c0ac7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4ce35c11d98add4706ac5202f0ba93017f4563cc0c1340b159fa5218a6fa98e2fd1f2c4523a70963656e8ace51509c5a994aac6974e682f04984ab7836ddb4e0
|
7
|
+
data.tar.gz: ad68072b8c05b903c84f225d0978014a9f8d4f2bf36404b5ef2d6a9956405035f1c4e61287c58fd0e25b6500426eb2a2dcf758741a3437088cf03e15caa253e6
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,16 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.3.1] - 2024-07-30
|
4
|
+
|
5
|
+
- Friendly I18n
|
6
|
+
|
7
|
+
## [0.3.0] - 2024-07-30
|
8
|
+
|
9
|
+
- on_inner_monologue: ->(text:) { puts Rainbow("monologue: #{text}").yellow }
|
10
|
+
- on_outer_voice: ->(text:) { puts Rainbow("voice: #{text}").green }
|
11
|
+
- on_action_request: ->(text:) { puts Rainbow("action: #{text}").red }
|
12
|
+
- on_pack_history: ->(text:) { puts Rainbow("summary: #{text}").blue }
|
13
|
+
|
3
14
|
## [0.2.5] - 2024-07-30
|
4
15
|
|
5
16
|
- Improved start template
|
data/README.md
CHANGED
@@ -28,8 +28,9 @@ Here's a basic example of how to use OxAiWorkers:
|
|
28
28
|
|
29
29
|
```ruby
|
30
30
|
# Load localization files and set default locale
|
31
|
-
|
32
|
-
|
31
|
+
# Uncomment this if you want to change the locale
|
32
|
+
# require 'oxaiworkers/load_i18n' # only for pure Ruby
|
33
|
+
# I18n.default_locale = :ru # only for pure Ruby
|
33
34
|
|
34
35
|
# Require the main gem
|
35
36
|
require 'ox-ai-workers'
|
@@ -101,10 +102,18 @@ assistant.addResponse("blah-blah-blah")
|
|
101
102
|
Or you can create a lower-level iterator for more control:
|
102
103
|
|
103
104
|
```ruby
|
105
|
+
my_worker = OxAiWorkers::Request.new
|
106
|
+
my_tool = OxAiWorkers::Tool::Eval.new
|
107
|
+
|
104
108
|
iterator = OxAiWorkers::Iterator.new(
|
105
|
-
|
106
|
-
|
107
|
-
|
109
|
+
worker: my_worker,
|
110
|
+
tools: [my_tool],
|
111
|
+
role: "You are a software agent inside my computer",
|
112
|
+
on_inner_monologue: ->(text:) { puts Rainbow("monologue: #{text}").yellow },
|
113
|
+
on_outer_voice: ->(text:) { puts Rainbow("voice: #{text}").green },
|
114
|
+
on_action_request: ->(text:) { puts Rainbow("action: #{text}").red },
|
115
|
+
on_pack_history: ->(text:) { puts Rainbow("summary: #{text}").blue }
|
116
|
+
)
|
108
117
|
|
109
118
|
iterator.addTask("Show files in current directory.")
|
110
119
|
# ...
|
@@ -131,7 +140,7 @@ As a worker, you can use different classes depending on your needs:
|
|
131
140
|
oxaiworkers init
|
132
141
|
```
|
133
142
|
|
134
|
-
This will create a `.oxaiworkers-local` directory with the necessary initial
|
143
|
+
This will create a `.oxaiworkers-local` directory with the necessary initial source code.
|
135
144
|
|
136
145
|
Additionally, you can initialize a more comprehensive example using the command:
|
137
146
|
|
data/exe/oxaiworkers
CHANGED
@@ -14,7 +14,7 @@ if ARGV.first == 'init'
|
|
14
14
|
puts "Error: The #{dir} directory already exists."
|
15
15
|
else
|
16
16
|
FileUtils.mkdir_p "#{dir}/locales"
|
17
|
-
FileUtils.copy_entry "#{source}/locales", "#{dest}/locales"
|
17
|
+
# FileUtils.copy_entry "#{source}/locales", "#{dest}/locales"
|
18
18
|
if ARGV.last == 'full'
|
19
19
|
FileUtils.copy_entry "#{source}/template", dest.to_s
|
20
20
|
else
|
data/exe/start
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
I18n.default_locale = :
|
4
|
+
# Uncomment this if you want to change the locale
|
5
|
+
# require 'oxaiworkers/load_i18n'
|
6
|
+
# I18n.default_locale = :ru
|
7
7
|
|
8
8
|
# Start your code here
|
9
9
|
require 'ox-ai-workers'
|
data/lib/ox-ai-workers.rb
CHANGED
@@ -1,31 +1,31 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
|
10
|
-
require_relative
|
11
|
-
require_relative
|
12
|
-
require_relative
|
13
|
-
require_relative
|
14
|
-
require_relative
|
15
|
-
require_relative
|
16
|
-
require_relative
|
17
|
-
require_relative
|
18
|
-
require_relative
|
19
|
-
require_relative
|
20
|
-
require_relative
|
21
|
-
require_relative
|
22
|
-
require_relative
|
23
|
-
|
24
|
-
require_relative
|
25
|
-
require_relative
|
3
|
+
require 'faraday'
|
4
|
+
require 'faraday/multipart'
|
5
|
+
require 'rainbow'
|
6
|
+
require 'openai'
|
7
|
+
require 'yaml'
|
8
|
+
require 'json'
|
9
|
+
|
10
|
+
require_relative 'oxaiworkers/version'
|
11
|
+
require_relative 'oxaiworkers/load_i18n'
|
12
|
+
require_relative 'oxaiworkers/present_compat'
|
13
|
+
require_relative 'oxaiworkers/module_request'
|
14
|
+
require_relative 'oxaiworkers/state_helper'
|
15
|
+
require_relative 'oxaiworkers/state_batch'
|
16
|
+
require_relative 'oxaiworkers/state_tools'
|
17
|
+
require_relative 'oxaiworkers/tool_definition'
|
18
|
+
require_relative 'oxaiworkers/delayed_request'
|
19
|
+
require_relative 'oxaiworkers/dependency_helper'
|
20
|
+
require_relative 'oxaiworkers/iterator'
|
21
|
+
require_relative 'oxaiworkers/request'
|
22
|
+
require_relative 'oxaiworkers/tool/eval'
|
23
|
+
|
24
|
+
require_relative 'oxaiworkers/assistant/module_base'
|
25
|
+
require_relative 'oxaiworkers/assistant/sysop'
|
26
26
|
|
27
27
|
module OxAiWorkers
|
28
|
-
DEFAULT_MODEL =
|
28
|
+
DEFAULT_MODEL = 'gpt-4o-mini'
|
29
29
|
DEFAULT_MAX_TOKEN = 4096
|
30
30
|
DEFAULT_TEMPERATURE = 0.7
|
31
31
|
|
@@ -33,8 +33,7 @@ module OxAiWorkers
|
|
33
33
|
class ConfigurationError < Error; end
|
34
34
|
|
35
35
|
class Configuration
|
36
|
-
|
37
|
-
attr_accessor :model, :max_tokens, :temperature
|
36
|
+
attr_accessor :model, :max_tokens, :temperature, :access_token
|
38
37
|
|
39
38
|
def initialize
|
40
39
|
@access_token = nil
|
@@ -42,15 +41,10 @@ module OxAiWorkers
|
|
42
41
|
@max_tokens = DEFAULT_MAX_TOKEN
|
43
42
|
@temperature = DEFAULT_TEMPERATURE
|
44
43
|
|
45
|
-
[Array, NilClass, String, Symbol, Hash].each
|
44
|
+
[Array, NilClass, String, Symbol, Hash].each do |c|
|
46
45
|
c.send(:include, OxAiWorkers::PresentCompat) unless c.method_defined?(:present?)
|
47
|
-
|
48
|
-
String.
|
49
|
-
|
50
|
-
end
|
51
|
-
|
52
|
-
def access_token
|
53
|
-
return @access_token
|
46
|
+
end
|
47
|
+
String.include OxAiWorkers::CamelizeCompat unless String.method_defined?(:camelize)
|
54
48
|
end
|
55
49
|
end
|
56
50
|
|
@@ -9,7 +9,11 @@ module OxAiWorkers
|
|
9
9
|
@iterator = OxAiWorkers::Iterator.new(
|
10
10
|
worker: initWorker(delayed: delayed, model: model),
|
11
11
|
role: I18n.t('oxaiworkers.assistant.sysop.role'),
|
12
|
-
tools: [OxAiWorkers::Tool::Eval.new]
|
12
|
+
tools: [OxAiWorkers::Tool::Eval.new],
|
13
|
+
on_inner_monologue: ->(text:) { puts Rainbow("monologue: #{text}").yellow },
|
14
|
+
on_outer_voice: ->(text:) { puts Rainbow("voice: #{text}").green },
|
15
|
+
on_action_request: ->(text:) { puts Rainbow("action: #{text}").red },
|
16
|
+
on_pack_history: ->(text:) { puts Rainbow("summary: #{text}").blue }
|
13
17
|
)
|
14
18
|
end
|
15
19
|
end
|
@@ -1,107 +1,109 @@
|
|
1
|
-
|
2
|
-
def initialize(batch_id: nil, model: nil, max_tokens: nil, temperature: nil)
|
3
|
-
initializeRequests(model: model, max_tokens: max_tokens, temperature: temperature)
|
4
|
-
@custom_id = nil if batch_id.present?
|
5
|
-
@batch_id = batch_id
|
6
|
-
@file_id = nil
|
7
|
-
super()
|
8
|
-
end
|
9
|
-
|
10
|
-
def postBatch
|
11
|
-
response = @client.batches.create(
|
12
|
-
parameters: {
|
13
|
-
input_file_id: @file_id,
|
14
|
-
endpoint: "/v1/chat/completions",
|
15
|
-
completion_window: "24h"
|
16
|
-
}
|
17
|
-
)
|
18
|
-
@batch_id = response["id"]
|
19
|
-
end
|
1
|
+
# frozen_string_literal: true
|
20
2
|
|
21
|
-
|
22
|
-
|
23
|
-
|
3
|
+
module OxAiWorkers
|
4
|
+
class DelayedRequest < OxAiWorkers::StateBatch
|
5
|
+
def initialize(batch_id: nil, model: nil, max_tokens: nil, temperature: nil)
|
6
|
+
initializeRequests(model: model, max_tokens: max_tokens, temperature: temperature)
|
7
|
+
@custom_id = nil if batch_id.present?
|
8
|
+
@batch_id = batch_id
|
9
|
+
@file_id = nil
|
10
|
+
super()
|
11
|
+
end
|
24
12
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
not_found_is_ok{ @client.files.delete(id: @file_id) } if @file_id.present? && @file_id != batch["input_file_id"]
|
35
|
-
elsif @file_id.present?
|
36
|
-
not_found_is_ok{ @client.files.delete(id: @file_id) }
|
13
|
+
def postBatch
|
14
|
+
response = @client.batches.create(
|
15
|
+
parameters: {
|
16
|
+
input_file_id: @file_id,
|
17
|
+
endpoint: '/v1/chat/completions',
|
18
|
+
completion_window: '24h'
|
19
|
+
}
|
20
|
+
)
|
21
|
+
@batch_id = response['id']
|
37
22
|
end
|
38
|
-
end
|
39
23
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
end
|
24
|
+
def cancelBatch
|
25
|
+
not_found_is_ok { @client.batches.cancel(id: @batch_id) }
|
26
|
+
end
|
44
27
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
28
|
+
def cleanStorage
|
29
|
+
if @batch_id.present?
|
30
|
+
batch = @client.batches.retrieve(id: @batch_id)
|
31
|
+
if !batch['output_file_id'].nil?
|
32
|
+
not_found_is_ok { @client.files.delete(id: batch['output_file_id']) }
|
33
|
+
elsif !batch['error_file_id'].nil?
|
34
|
+
not_found_is_ok { @client.files.delete(id: batch['error_file_id']) }
|
35
|
+
end
|
36
|
+
not_found_is_ok { @client.files.delete(id: batch['input_file_id']) }
|
37
|
+
if @file_id.present? && @file_id != batch['input_file_id']
|
38
|
+
not_found_is_ok do
|
39
|
+
@client.files.delete(id: @file_id)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
elsif @file_id.present?
|
43
|
+
not_found_is_ok { @client.files.delete(id: @file_id) }
|
44
|
+
end
|
45
|
+
end
|
52
46
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
begin
|
57
|
-
response = @client.files.upload(parameters: { file: file.path, purpose: "batch"} )
|
58
|
-
@file_id = response["id"]
|
59
|
-
process_batch!
|
60
|
-
rescue OpenAI::Error => e
|
61
|
-
puts e.inspect
|
62
|
-
fail_batch!
|
47
|
+
def finish
|
48
|
+
@custom_id = SecureRandom.uuid
|
49
|
+
end_batch! unless batch_idle?
|
63
50
|
end
|
64
|
-
file.unlink
|
65
|
-
end
|
66
51
|
|
67
|
-
|
68
|
-
|
69
|
-
|
52
|
+
def uploadToStorage
|
53
|
+
item = {
|
54
|
+
"custom_id": @custom_id,
|
55
|
+
"method": 'POST',
|
56
|
+
"url": '/v1/chat/completions',
|
57
|
+
"body": params
|
58
|
+
}
|
70
59
|
|
71
|
-
|
72
|
-
|
73
|
-
|
60
|
+
file = Tempfile.new(["batch_#{@custom_id}", '.jsonl'])
|
61
|
+
file.write item.to_json
|
62
|
+
file.close
|
63
|
+
begin
|
64
|
+
response = @client.files.upload(parameters: { file: file.path, purpose: 'batch' })
|
65
|
+
@file_id = response['id']
|
66
|
+
process_batch!
|
67
|
+
rescue OpenAI::Error => e
|
68
|
+
puts e.inspect
|
69
|
+
fail_batch!
|
70
|
+
end
|
71
|
+
file.unlink
|
72
|
+
end
|
74
73
|
|
75
|
-
|
76
|
-
|
77
|
-
batch = @client.batches.retrieve(id: @batch_id)
|
78
|
-
if batch["status"] == "failed"
|
79
|
-
@errors = batch["errors"]["data"].map{|e| e["message"]}
|
80
|
-
fail_batch!
|
81
|
-
return true
|
82
|
-
elsif batch["status"] != "completed"
|
83
|
-
return false
|
74
|
+
def request!
|
75
|
+
prepare_batch! if @messages.any?
|
84
76
|
end
|
85
77
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
78
|
+
def cancel
|
79
|
+
cancel_batch!
|
80
|
+
end
|
81
|
+
|
82
|
+
def completed?
|
83
|
+
return false if @batch_id.nil?
|
84
|
+
|
85
|
+
batch = @client.batches.retrieve(id: @batch_id)
|
86
|
+
if batch['status'] == 'failed'
|
87
|
+
@errors = batch['errors']['data'].map { |e| e['message'] }
|
88
|
+
fail_batch!
|
89
|
+
return true
|
90
|
+
elsif batch['status'] != 'completed'
|
91
|
+
return false
|
92
|
+
end
|
93
|
+
|
94
|
+
if !batch['output_file_id'].nil?
|
95
|
+
output = @client.files.content(id: batch['output_file_id'])
|
96
|
+
output.each do |line|
|
97
|
+
@custom_id = line['custom_id']
|
98
|
+
# @result = line.dig("response", "body", "choices", 0, "message", "content")
|
99
|
+
parseChoices(line.dig('response', 'body'))
|
100
|
+
complete_batch!
|
101
|
+
end
|
102
|
+
elsif !batch['error_file_id'].nil?
|
103
|
+
@errors = @client.files.content(id: batch['error_file_id'])
|
104
|
+
fail_batch!
|
105
|
+
end
|
106
|
+
true
|
107
|
+
end
|
99
108
|
end
|
100
109
|
end
|
101
|
-
|
102
|
-
# r = OxAiWorkers::DelayedRequest.new
|
103
|
-
# r.append(role: "user", content: "сколько будет 2+2?")
|
104
|
-
# r.request!
|
105
|
-
# r.completed?
|
106
|
-
# r.result
|
107
|
-
# r.finish
|