ox-ai-workers 0.9.3.1 → 0.9.5
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 +13 -0
- data/README.md +92 -1
- data/config/locales/en.oxaiworkers.tool.yml +4 -4
- data/config/locales/ru.oxaiworkers.tool.yml +3 -3
- data/lib/ox-ai-workers.rb +9 -2
- data/lib/oxaiworkers/assistant/painter.rb +6 -3
- data/lib/oxaiworkers/iterator.rb +19 -2
- data/lib/oxaiworkers/models/deepseek_max.rb +1 -3
- data/lib/oxaiworkers/models/images_base.rb +11 -0
- data/lib/oxaiworkers/models/{module_base.rb → llm_base.rb} +1 -1
- data/lib/oxaiworkers/models/openai_dalle3.rb +47 -0
- data/lib/oxaiworkers/models/openai_gpt_image.rb +37 -0
- data/lib/oxaiworkers/models/openai_max.rb +1 -3
- data/lib/oxaiworkers/models/stability_images.rb +32 -0
- data/lib/oxaiworkers/module_request.rb +17 -4
- data/lib/oxaiworkers/tool/pixels.rb +23 -42
- data/lib/oxaiworkers/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c008f2f4f413251ffa88e00935e118c9844b2e67ab5088ca1091f2b7ac64ac77
|
4
|
+
data.tar.gz: a9b4cf53a19322a10db55ffa480d1e9bfe3a587411398ca5797058f5941c6ee8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ac9053e4092115ef23a2f39d834c511c91d9594d8fc8ba37af95652917879ff5cd390581d2bb6d37d184af61d2809a9292c33375c8bd3d06eccb4b84a29ad2ff
|
7
|
+
data.tar.gz: 907e52e93352af84f3bc7b38ef02180dc1a4850f645bb40c7e36d371e85c1a8cdb00e60aa9805d91834b01437c3ae2ff5eb60746e379ec0bfae65a147b627c5c
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
|
2
|
+
## [0.9.5] - 2025-05-10
|
3
|
+
|
4
|
+
- Added `call_stack` for `Iterator` and `ModuleRequest`
|
5
|
+
- Added `stop_double_calls` for `Iterator` and `ModuleRequest`
|
6
|
+
|
7
|
+
## [0.9.4] - 2025-05-08
|
8
|
+
|
9
|
+
- Added `stability_images` model
|
10
|
+
- Added `openai_gpt_image` model
|
11
|
+
- Added `openai_dalle3` model
|
12
|
+
- Added `access_token_stability` for configuration
|
13
|
+
|
1
14
|
## [0.9.3] - 2025-05-06
|
2
15
|
|
3
16
|
- Changed `max_tokens` to `max_completion_tokens` in `params`
|
data/README.md
CHANGED
@@ -154,14 +154,25 @@ steps << "Step 4. When the solution is ready, notify about it and wait for the u
|
|
154
154
|
# To retain the locale if you have assistants in different languages in your project.
|
155
155
|
store_locale # Optional
|
156
156
|
|
157
|
+
tool = MyTool.new
|
158
|
+
|
157
159
|
@iterator = OxAiWorkers::Iterator.new(
|
158
160
|
worker: init_worker(delayed: delayed, model: model),
|
159
161
|
role: 'You are a software agent inside my computer',
|
160
|
-
tools: [
|
162
|
+
tools: [tool],
|
161
163
|
locale: @locale || I18n.locale,
|
162
164
|
steps: steps,
|
163
165
|
# def_except: [:outer_voice], # It's except steps with that functions
|
164
166
|
# def_only: [:inner_monologue, :outer_voice], # Use it only with your steps
|
167
|
+
# Forced Function: Uses call_stack parameter to force the model to call functions in this exact order, one at a time
|
168
|
+
# call_stack: [
|
169
|
+
# OxAiWorkers::Iterator.full_function_name(:outer_voice),
|
170
|
+
# tool.full_function_name(:func1)
|
171
|
+
# ],
|
172
|
+
# Stop Double Calls: Uses stop_double_calls parameter to prevent the model from calling the same function twice in a row
|
173
|
+
# stop_double_calls: [
|
174
|
+
# tool.full_function_name(:func1)
|
175
|
+
# ],
|
165
176
|
on_inner_monologue: ->(text:) { puts "monologue: #{text}".colorize(:yellow) },
|
166
177
|
on_outer_voice: ->(text:) { puts "voice: #{text}".colorize(:green) }
|
167
178
|
)
|
@@ -438,6 +449,86 @@ OxAiWorkers provides several specialized assistant types:
|
|
438
449
|
localizer.task = "Translate my application's interface"
|
439
450
|
```
|
440
451
|
|
452
|
+
- **Painter**: Image generation and manipulation
|
453
|
+
|
454
|
+
```ruby
|
455
|
+
painter = OxAiWorkers::Assistant::Painter.new
|
456
|
+
# or Set working directory to save generated images as files
|
457
|
+
# painter = OxAiWorkers::Assistant::Painter.new(current_dir: Dir.pwd)
|
458
|
+
painter.task = "Create an image of a sunset over mountains"
|
459
|
+
```
|
460
|
+
|
461
|
+
- **Orchestrator**: Coordinates multiple assistants to work together on complex tasks
|
462
|
+
|
463
|
+
```ruby
|
464
|
+
orchestrator = OxAiWorkers::Assistant::Orchestrator.new(
|
465
|
+
workflow: 'Development team creates an application and tests it.'
|
466
|
+
)
|
467
|
+
orchestrator.add_assistant(OxAiWorkers::Assistant::Coder.new)
|
468
|
+
orchestrator.add_assistant(OxAiWorkers::Assistant::Sysop.new)
|
469
|
+
orchestrator.add_assistant(OxAiWorkers::Assistant::Localizer.new)
|
470
|
+
orchestrator.task = "Create a hello world application in C, save it to hello_world.c, compile, run, and verify it works."
|
471
|
+
```
|
472
|
+
|
473
|
+
### Available Tools
|
474
|
+
|
475
|
+
OxAiWorkers provides several specialized tools to extend functionality:
|
476
|
+
|
477
|
+
- **Pixels**: Image generation and manipulation tool
|
478
|
+
|
479
|
+
```ruby
|
480
|
+
# Initialize with worker and optional parameters
|
481
|
+
pixels = OxAiWorkers::Tool::Pixels.new(
|
482
|
+
worker: worker, # Required: Request or DelayedRequest instance
|
483
|
+
current_dir: Dir.pwd, # Optional: Directory to save generated images
|
484
|
+
image_model: 'dall-e-3', # Optional: 'dall-e-3' or 'gpt-image-1'
|
485
|
+
only: [:generate_image] # Optional: Limit available functions
|
486
|
+
)
|
487
|
+
```
|
488
|
+
|
489
|
+
Provides functions for generating images with customizable parameters like size and quality, with ability to save generated images to disk.
|
490
|
+
|
491
|
+
- **Pipeline**: Assistant coordination and communication tool
|
492
|
+
|
493
|
+
```ruby
|
494
|
+
# Initialize with optional parameters
|
495
|
+
pipeline = OxAiWorkers::Tool::Pipeline.new(
|
496
|
+
on_message: ->(text:) { puts text } # Optional: Message handler callback
|
497
|
+
)
|
498
|
+
|
499
|
+
# Add assistants to the pipeline
|
500
|
+
pipeline.add_assistant(OxAiWorkers::Assistant::Coder.new)
|
501
|
+
pipeline.add_assistant(OxAiWorkers::Assistant::Sysop.new)
|
502
|
+
```
|
503
|
+
|
504
|
+
Enables communication between multiple assistants, maintaining message context and facilitating collaborative problem-solving.
|
505
|
+
|
506
|
+
- **Eval**: Code execution tool
|
507
|
+
|
508
|
+
```ruby
|
509
|
+
# Initialize with optional parameters
|
510
|
+
eval_tool = OxAiWorkers::Tool::Eval.new(
|
511
|
+
only: [:ruby, :sh], # Optional: Limit available functions
|
512
|
+
current_dir: Dir.pwd # Optional: Directory to execute commands in
|
513
|
+
)
|
514
|
+
```
|
515
|
+
|
516
|
+
Allows execution of Ruby code and shell commands, with directory context support.
|
517
|
+
|
518
|
+
- **FileSystem**: File operations tool
|
519
|
+
|
520
|
+
```ruby
|
521
|
+
# Initialize with optional parameters
|
522
|
+
file_system = OxAiWorkers::Tool::FileSystem.new(
|
523
|
+
current_dir: Dir.pwd, # Optional: Base directory for operations
|
524
|
+
only: [:list_directory, :read_file, :write_to_file] # Optional: Limit available functions
|
525
|
+
)
|
526
|
+
```
|
527
|
+
|
528
|
+
Provides functions for listing directory contents, reading from files, and writing to files with support for relative paths.
|
529
|
+
|
530
|
+
Additional tools like Database and Converter are available for specialized tasks and can be integrated using the same pattern.
|
531
|
+
|
441
532
|
### Implementing Your Own Assistant
|
442
533
|
|
443
534
|
Create custom assistants by inheriting from existing ones or composing with the Iterator:
|
@@ -40,8 +40,8 @@ en:
|
|
40
40
|
assistant_info: "ID: **%{id}**, Title: %{title}\nRole: %{role}\nDescription: %{description}\nCapabilities: %{capabilities}"
|
41
41
|
pixels:
|
42
42
|
generate_image:
|
43
|
-
description: 'Image Generation Tool: Creates an image based on the provided text prompt
|
44
|
-
prompt: 'Text description of the image to generate'
|
45
|
-
size: 'Size of the generated image
|
46
|
-
quality: 'Quality of the generated image
|
43
|
+
description: 'Image Generation Tool: Creates an image based on the provided text prompt on **English language**.'
|
44
|
+
prompt: 'Text description of the image to generate on **English language**'
|
45
|
+
size: 'Size of the generated image'
|
46
|
+
quality: 'Quality of the generated image'
|
47
47
|
file_name: 'File name for saving the generated image in png format. For example: image.png'
|
@@ -40,12 +40,12 @@ ru:
|
|
40
40
|
assistant_info: "ID: **%{id}**, Название: %{title}\nРоль: %{role}\nОписание: %{description}\nВозможности: %{capabilities}"
|
41
41
|
pixels:
|
42
42
|
generate_image:
|
43
|
-
description: 'Инструмент генерации изображений: Создает изображение на основе предоставленного текстового
|
44
|
-
prompt: 'Текстовое описание изображения для генерации'
|
43
|
+
description: 'Инструмент генерации изображений: Создает изображение на основе предоставленного текстового запроса на **английском языке**.'
|
44
|
+
prompt: 'Текстовое описание изображения для генерации строго **на английском** языке'
|
45
45
|
size: 'Размер генерируемого изображения'
|
46
46
|
quality: 'Качество генерируемого изображения'
|
47
47
|
file_name: 'Имя файла для сохранения изображения в формате png. Например: image.png'
|
48
48
|
edit_image:
|
49
|
-
description: 'Инструмент редактирования изображений: Редактирует изображение на основе предоставленного текстового запроса.
|
49
|
+
description: 'Инструмент редактирования изображений: Редактирует изображение на основе предоставленного текстового запроса.'
|
50
50
|
input_image: 'URL или путь к изображению для редактирования'
|
51
51
|
prompt: 'Текстовое описание действий для редактирования изображения'
|
data/lib/ox-ai-workers.rb
CHANGED
@@ -36,12 +36,17 @@ require_relative 'oxaiworkers/assistant/localizer'
|
|
36
36
|
require_relative 'oxaiworkers/assistant/orchestrator'
|
37
37
|
require_relative 'oxaiworkers/assistant/painter'
|
38
38
|
|
39
|
-
require_relative 'oxaiworkers/models/
|
39
|
+
require_relative 'oxaiworkers/models/llm_base'
|
40
40
|
require_relative 'oxaiworkers/models/openai_max'
|
41
41
|
require_relative 'oxaiworkers/models/openai_mini'
|
42
42
|
require_relative 'oxaiworkers/models/openai_nano'
|
43
43
|
require_relative 'oxaiworkers/models/deepseek_max'
|
44
44
|
|
45
|
+
require_relative 'oxaiworkers/models/images_base'
|
46
|
+
require_relative 'oxaiworkers/models/stability_images'
|
47
|
+
require_relative 'oxaiworkers/models/openai_gpt_image'
|
48
|
+
require_relative 'oxaiworkers/models/openai_dalle3'
|
49
|
+
|
45
50
|
require_relative 'oxaiworkers/engine' if defined?(Rails)
|
46
51
|
|
47
52
|
module OxAiWorkers
|
@@ -52,7 +57,8 @@ module OxAiWorkers
|
|
52
57
|
class ConfigurationError < Error; end
|
53
58
|
|
54
59
|
class Configuration
|
55
|
-
attr_accessor :max_tokens, :temperature, :wait_for_complete, :access_token_deepseek, :access_token_openai
|
60
|
+
attr_accessor :max_tokens, :temperature, :wait_for_complete, :access_token_deepseek, :access_token_openai,
|
61
|
+
:access_token_stability
|
56
62
|
|
57
63
|
def initialize
|
58
64
|
@max_tokens = DEFAULT_MAX_TOKEN
|
@@ -61,6 +67,7 @@ module OxAiWorkers
|
|
61
67
|
|
62
68
|
@access_token_deepseek = nil
|
63
69
|
@access_token_openai = nil
|
70
|
+
@access_token_stability = nil
|
64
71
|
|
65
72
|
[Array, NilClass, String, Symbol, Hash].each do |c|
|
66
73
|
c.send(:include, OxAiWorkers::PresentCompat) unless c.method_defined?(:present?)
|
@@ -5,7 +5,7 @@ module OxAiWorkers
|
|
5
5
|
class Painter
|
6
6
|
include OxAiWorkers::Assistant::ModuleBase
|
7
7
|
|
8
|
-
def initialize(current_dir: nil, delayed: false, model: nil)
|
8
|
+
def initialize(current_dir: nil, delayed: false, model: nil, image_model: nil)
|
9
9
|
store_locale
|
10
10
|
@current_dir = current_dir
|
11
11
|
|
@@ -17,10 +17,13 @@ module OxAiWorkers
|
|
17
17
|
@title = I18n.t('oxaiworkers.assistant.painter.title')
|
18
18
|
end
|
19
19
|
|
20
|
+
worker = init_worker(delayed:, model:)
|
21
|
+
image_model ||= OxAiWorkers::Models::OpenaiDalle3.new
|
22
|
+
|
20
23
|
@iterator = Iterator.new(
|
21
|
-
worker
|
24
|
+
worker:,
|
22
25
|
role: @role,
|
23
|
-
tools: [Tool::Pixels.new(worker:
|
26
|
+
tools: [Tool::Pixels.new(worker: image_model, current_dir:)],
|
24
27
|
locale: @locale,
|
25
28
|
on_inner_monologue: ->(text:) { puts "monologue: #{text}".colorize(:yellow) },
|
26
29
|
on_outer_voice: ->(text:) { puts "voice: #{text}".colorize(:green) }
|
data/lib/oxaiworkers/iterator.rb
CHANGED
@@ -8,10 +8,12 @@ module OxAiWorkers
|
|
8
8
|
include OxAiWorkers::LoadI18n
|
9
9
|
|
10
10
|
attr_accessor :worker, :role, :messages, :context, :tools, :queue, :monologue, :tasks,
|
11
|
-
:on_inner_monologue, :on_outer_voice, :on_finish, :def_except, :def_only
|
11
|
+
:on_inner_monologue, :on_outer_voice, :on_finish, :def_except, :def_only,
|
12
|
+
:call_stack, :stop_double_calls
|
12
13
|
|
13
14
|
def initialize(worker:, role: nil, tools: [], on_inner_monologue: nil, on_outer_voice: nil,
|
14
|
-
on_finish: nil, steps: nil, def_except: [], def_only: nil, locale: nil
|
15
|
+
on_finish: nil, steps: nil, def_except: [], def_only: nil, locale: nil,
|
16
|
+
call_stack: nil, stop_double_calls: [])
|
15
17
|
|
16
18
|
@locale = locale || I18n.locale
|
17
19
|
|
@@ -41,6 +43,18 @@ module OxAiWorkers
|
|
41
43
|
@on_outer_voice = on_outer_voice
|
42
44
|
@on_finish = on_finish
|
43
45
|
|
46
|
+
if call_stack&.any?
|
47
|
+
if available_defs.include?(:inner_monologue) && !call_stack.include?(OxAiWorkers::Iterator.full_function_name(:inner_monologue))
|
48
|
+
# Add inner_monologue first
|
49
|
+
@call_stack = [OxAiWorkers::Iterator.full_function_name(:inner_monologue)] + call_stack
|
50
|
+
end
|
51
|
+
# Add finish_it last
|
52
|
+
@call_stack = call_stack + [OxAiWorkers::Iterator.full_function_name(:finish_it)]
|
53
|
+
end
|
54
|
+
|
55
|
+
@stop_double_calls = [OxAiWorkers::Iterator.full_function_name(:inner_monologue),
|
56
|
+
OxAiWorkers::Iterator.full_function_name(:outer_voice)] + stop_double_calls
|
57
|
+
|
44
58
|
cleanup
|
45
59
|
|
46
60
|
super()
|
@@ -99,6 +113,9 @@ module OxAiWorkers
|
|
99
113
|
end
|
100
114
|
|
101
115
|
def rebuild_worker
|
116
|
+
@worker.last_call = nil
|
117
|
+
@worker.call_stack = @call_stack.dup
|
118
|
+
@worker.stop_double_calls = @stop_double_calls
|
102
119
|
@worker.messages = []
|
103
120
|
@worker.append(role: :system, content: @role) if @role.present?
|
104
121
|
|
@@ -2,9 +2,7 @@
|
|
2
2
|
|
3
3
|
module OxAiWorkers
|
4
4
|
module Models
|
5
|
-
class DeepseekMax
|
6
|
-
include OxAiWorkers::Models::ModuleBase
|
7
|
-
|
5
|
+
class DeepseekMax < LLMBase
|
8
6
|
def initialize(uri_base: nil, api_key: nil, model: nil, max_tokens: nil, temperature: nil, frequency_penalty: nil)
|
9
7
|
@model = model || 'deepseek-chat'
|
10
8
|
@uri_base = uri_base || 'https://api.deepseek.com/'
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module OxAiWorkers
|
4
4
|
module Models
|
5
|
-
|
5
|
+
class LLMBase
|
6
6
|
attr_accessor :uri_base, :api_key, :model, :max_tokens, :temperature, :frequency_penalty
|
7
7
|
|
8
8
|
def initialize(uri_base:, api_key:, model:, max_tokens: nil, temperature: nil, frequency_penalty: nil)
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module OxAiWorkers
|
2
|
+
module Models
|
3
|
+
class OpenaiDalle3 < ImagesBase
|
4
|
+
def initialize(api_key: nil, options: {})
|
5
|
+
@sizes = %w[1024x1024 1024x1792 1792x1024]
|
6
|
+
@qualities = %w[standard hd]
|
7
|
+
api_key ||= OxAiWorkers.configuration.access_token_openai
|
8
|
+
|
9
|
+
@client = OpenAI::Client.new(access_token: api_key)
|
10
|
+
super(options:)
|
11
|
+
end
|
12
|
+
|
13
|
+
def generate(prompt:, size: nil, quality: nil)
|
14
|
+
puts "OpenaiDalle3: #{prompt}"
|
15
|
+
|
16
|
+
size ||= @sizes.first
|
17
|
+
quality ||= @qualities.first
|
18
|
+
|
19
|
+
options = {
|
20
|
+
prompt:,
|
21
|
+
model: 'dall-e-3',
|
22
|
+
size:,
|
23
|
+
quality:
|
24
|
+
}
|
25
|
+
options.merge!(@options)
|
26
|
+
|
27
|
+
response = @client.images.generate(
|
28
|
+
parameters: options
|
29
|
+
)
|
30
|
+
|
31
|
+
url = response.dig('data', 0, 'url')
|
32
|
+
b64_json = response.dig('data', 0, 'b64_json')
|
33
|
+
revised_prompt = response.dig('data', 0, 'revised_prompt')
|
34
|
+
|
35
|
+
@result = "revised_prompt: #{revised_prompt}\n\n"
|
36
|
+
if url.present?
|
37
|
+
@result += "url: #{url}\n\n"
|
38
|
+
URI.open(url).read
|
39
|
+
elsif b64_json.present?
|
40
|
+
Base64.decode64(b64_json)
|
41
|
+
else
|
42
|
+
nil
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module OxAiWorkers
|
2
|
+
module Models
|
3
|
+
class OpenaiGptImage < ImagesBase
|
4
|
+
def initialize(api_key: nil, options: {})
|
5
|
+
@sizes = %w[auto 1024x1024 1536x1024 1024x1536]
|
6
|
+
@qualities = %w[auto low medium high]
|
7
|
+
api_key ||= OxAiWorkers.configuration.access_token_openai
|
8
|
+
|
9
|
+
@client = OpenAI::Client.new(access_token: api_key)
|
10
|
+
super(options:)
|
11
|
+
end
|
12
|
+
|
13
|
+
def generate(prompt:, size: nil, quality: nil)
|
14
|
+
puts "OpenaiGptImage: #{prompt}"
|
15
|
+
|
16
|
+
size ||= @sizes.first
|
17
|
+
quality ||= @qualities.first
|
18
|
+
|
19
|
+
options = {
|
20
|
+
prompt:,
|
21
|
+
model: 'gpt-image-1',
|
22
|
+
size:,
|
23
|
+
quality:
|
24
|
+
}
|
25
|
+
options.merge!(@options)
|
26
|
+
|
27
|
+
response = @client.images.generate(
|
28
|
+
parameters: options
|
29
|
+
)
|
30
|
+
|
31
|
+
b64_json = response.dig('data', 0, 'b64_json')
|
32
|
+
|
33
|
+
Base64.decode64(b64_json)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -2,9 +2,7 @@
|
|
2
2
|
|
3
3
|
module OxAiWorkers
|
4
4
|
module Models
|
5
|
-
class OpenaiMax
|
6
|
-
include OxAiWorkers::Models::ModuleBase
|
7
|
-
|
5
|
+
class OpenaiMax < LLMBase
|
8
6
|
def initialize(uri_base: nil, api_key: nil, model: nil, max_tokens: nil, temperature: nil, frequency_penalty: nil)
|
9
7
|
@model = model || 'gpt-4.1'
|
10
8
|
@api_key = api_key || OxAiWorkers.configuration.access_token_openai
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module OxAiWorkers
|
2
|
+
module Models
|
3
|
+
class StabilityImages < ImagesBase
|
4
|
+
def initialize(api_key: nil, timeout: 300, options: {})
|
5
|
+
@sizes = %w[auto]
|
6
|
+
@qualities = %w[auto]
|
7
|
+
api_key ||= OxAiWorkers.configuration.access_token_stability
|
8
|
+
|
9
|
+
@client = StabilitySDK::Client.new(api_key:, timeout:)
|
10
|
+
super(options:)
|
11
|
+
end
|
12
|
+
|
13
|
+
def generate(prompt:, size: nil, quality: nil)
|
14
|
+
puts "StabilityImages: #{prompt}"
|
15
|
+
options = {
|
16
|
+
engine_id: 'stable-diffusion-xl-1024-v1-0'
|
17
|
+
}
|
18
|
+
options.merge!(@options)
|
19
|
+
binary = nil
|
20
|
+
@client.generate(prompt, options) do |answer|
|
21
|
+
answer.artifacts.each do |artifact|
|
22
|
+
next unless artifact.type == :ARTIFACT_IMAGE
|
23
|
+
|
24
|
+
binary = artifact.binary
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
binary
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -3,15 +3,17 @@
|
|
3
3
|
module OxAiWorkers
|
4
4
|
class ModuleRequest
|
5
5
|
attr_accessor :result, :client, :messages, :model, :custom_id, :tools, :errors,
|
6
|
-
:tool_calls_raw, :tool_calls, :is_truncated, :finish_reason,
|
6
|
+
:tool_calls_raw, :tool_calls, :is_truncated, :finish_reason,
|
7
|
+
:on_stream_proc, :call_stack, :last_call, :stop_double_calls
|
7
8
|
|
8
|
-
def initialize_requests(model:, on_stream: nil)
|
9
|
+
def initialize_requests(model:, on_stream: nil, call_stack: nil)
|
9
10
|
@custom_id = SecureRandom.uuid
|
10
11
|
@model = model
|
11
12
|
@client = nil
|
12
13
|
@is_truncated = false
|
13
14
|
@finish_reason = nil
|
14
15
|
@on_stream_proc = on_stream
|
16
|
+
@call_stack = call_stack
|
15
17
|
|
16
18
|
if @model.api_key.nil?
|
17
19
|
error_text = "#{@model.model} access token missing!"
|
@@ -34,6 +36,7 @@ module OxAiWorkers
|
|
34
36
|
@tool_calls_raw = nil
|
35
37
|
@is_truncated = false
|
36
38
|
@finish_reason = nil
|
39
|
+
@last_call = nil
|
37
40
|
end
|
38
41
|
|
39
42
|
def append(role: nil, content: nil, messages: nil)
|
@@ -50,8 +53,17 @@ module OxAiWorkers
|
|
50
53
|
frequency_penalty: @model.frequency_penalty
|
51
54
|
}
|
52
55
|
if @tools.present?
|
53
|
-
parameters[:tools] = @tools
|
54
|
-
|
56
|
+
parameters[:tools] = @tools.reject do |f|
|
57
|
+
tool_name = f[:function][:name]
|
58
|
+
tool_name == @last_call && @stop_double_calls.include?(tool_name)
|
59
|
+
end
|
60
|
+
if @call_stack&.any?
|
61
|
+
func1 = @call_stack.first
|
62
|
+
@call_stack = @call_stack.drop(1)
|
63
|
+
parameters[:tool_choice] = { type: 'function', function: { name: func1 } }
|
64
|
+
else
|
65
|
+
parameters[:tool_choice] = 'required'
|
66
|
+
end
|
55
67
|
end
|
56
68
|
if @on_stream_proc.present?
|
57
69
|
parameters[:stream] = @on_stream_proc
|
@@ -134,6 +146,7 @@ module OxAiWorkers
|
|
134
146
|
name: function['name'].split('__').last,
|
135
147
|
args: args
|
136
148
|
}
|
149
|
+
@last_call = function['name']
|
137
150
|
end
|
138
151
|
end
|
139
152
|
end
|
@@ -8,22 +8,9 @@ module OxAiWorkers
|
|
8
8
|
include OxAiWorkers::DependencyHelper
|
9
9
|
include OxAiWorkers::LoadI18n
|
10
10
|
|
11
|
-
attr_accessor :worker, :
|
12
|
-
|
13
|
-
|
14
|
-
'dall-e-3' => {
|
15
|
-
'model' => 'dall-e-3',
|
16
|
-
'size' => %w[1024x1024 1024x1792 1792x1024],
|
17
|
-
'quality' => %w[standard hd]
|
18
|
-
},
|
19
|
-
'gpt-image-1' => {
|
20
|
-
'model' => 'gpt-image-1',
|
21
|
-
'size' => %w[1024x1024 1024x1792 1792x1024],
|
22
|
-
'quality' => %w[auto low medium high]
|
23
|
-
}
|
24
|
-
}
|
25
|
-
|
26
|
-
def initialize(worker:, current_dir: nil, only: nil, image_model: 'dall-e-3', mask: nil)
|
11
|
+
attr_accessor :worker, :current_dir
|
12
|
+
|
13
|
+
def initialize(worker:, current_dir: nil, only: nil)
|
27
14
|
store_locale
|
28
15
|
|
29
16
|
init_white_list_with only
|
@@ -31,15 +18,19 @@ module OxAiWorkers
|
|
31
18
|
define_function :generate_image, description: I18n.t('oxaiworkers.tool.pixels.generate_image.description') do
|
32
19
|
property :prompt, type: 'string', description: I18n.t('oxaiworkers.tool.pixels.generate_image.prompt'),
|
33
20
|
required: true
|
34
|
-
|
35
|
-
|
21
|
+
if worker.sizes.length > 1
|
22
|
+
property :size, type: 'string', description: I18n.t('oxaiworkers.tool.pixels.generate_image.size'),
|
23
|
+
enum: worker.sizes
|
24
|
+
end
|
36
25
|
if current_dir.present?
|
37
26
|
property :file_name, type: 'string',
|
38
27
|
description: I18n.t('oxaiworkers.tool.pixels.generate_image.file_name'),
|
39
28
|
required: true
|
40
29
|
end
|
41
|
-
|
42
|
-
|
30
|
+
if worker.qualities.length > 1
|
31
|
+
property :quality, type: 'string', description: I18n.t('oxaiworkers.tool.pixels.generate_image.quality'),
|
32
|
+
enum: worker.qualities
|
33
|
+
end
|
43
34
|
end
|
44
35
|
|
45
36
|
# define_function :edit_image, description: I18n.t('oxaiworkers.tool.pixels.edit_image.description') do
|
@@ -56,32 +47,18 @@ module OxAiWorkers
|
|
56
47
|
|
57
48
|
@worker = worker
|
58
49
|
@current_dir = current_dir
|
59
|
-
@image_model = MODELS[image_model]
|
60
|
-
@mask = mask
|
61
50
|
end
|
62
51
|
|
63
52
|
def generate_image(prompt:, file_name: nil, size: nil, quality: nil)
|
64
|
-
|
65
|
-
|
66
|
-
size ||= @image_model['size'].first
|
67
|
-
quality ||= @image_model['quality'].first
|
68
|
-
|
69
|
-
response = @worker.client.images.generate(
|
70
|
-
parameters: {
|
71
|
-
prompt:,
|
72
|
-
model: @image_model['model'],
|
73
|
-
size:,
|
74
|
-
quality:
|
75
|
-
}
|
76
|
-
)
|
53
|
+
binary = @worker.generate(prompt:, size:, quality:)
|
77
54
|
|
78
|
-
@url = response.dig('data', 0, 'url')
|
79
|
-
revised_prompt = response.dig('data', 0, 'revised_prompt')
|
80
55
|
if file_name.present?
|
81
|
-
path = save_generated_image(file_name:)
|
82
|
-
"
|
56
|
+
path = save_generated_image(file_name:, binary:)
|
57
|
+
"Successfully generated image. file_name: #{path}\n\n#{@worker.result}"
|
58
|
+
elsif @worker.result.present?
|
59
|
+
@worker.result
|
83
60
|
else
|
84
|
-
|
61
|
+
'file_name not set for OxAiWorkers::Tool::Pixels. Please set file name first.'
|
85
62
|
end
|
86
63
|
end
|
87
64
|
|
@@ -109,20 +86,24 @@ module OxAiWorkers
|
|
109
86
|
end
|
110
87
|
end
|
111
88
|
|
112
|
-
def save_generated_image(file_name:)
|
89
|
+
def save_generated_image(file_name:, binary:)
|
113
90
|
unless @current_dir.present?
|
114
91
|
return 'Current directory not set for OxAiWorkers::Tool::Pixels. Please set current directory first.'
|
115
92
|
end
|
116
93
|
|
94
|
+
return 'File name not set for OxAiWorkers::Tool::Pixels. Please set file name first.' unless file_name.present?
|
95
|
+
|
117
96
|
# Ensure current_dir exists
|
118
97
|
FileUtils.mkdir_p(@current_dir) unless Dir.exist?(@current_dir)
|
119
98
|
|
120
99
|
path = File.join(@current_dir, file_name)
|
121
100
|
|
122
101
|
File.open(path, 'wb') do |file|
|
123
|
-
file.write(
|
102
|
+
file.write(binary)
|
124
103
|
end
|
125
104
|
|
105
|
+
puts "Successfully saved image. file_name: #{path}"
|
106
|
+
|
126
107
|
file_name
|
127
108
|
end
|
128
109
|
end
|
data/lib/oxaiworkers/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ox-ai-workers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Denis Smolev
|
@@ -155,10 +155,14 @@ files:
|
|
155
155
|
- lib/oxaiworkers/iterator.rb
|
156
156
|
- lib/oxaiworkers/load_i18n.rb
|
157
157
|
- lib/oxaiworkers/models/deepseek_max.rb
|
158
|
-
- lib/oxaiworkers/models/
|
158
|
+
- lib/oxaiworkers/models/images_base.rb
|
159
|
+
- lib/oxaiworkers/models/llm_base.rb
|
160
|
+
- lib/oxaiworkers/models/openai_dalle3.rb
|
161
|
+
- lib/oxaiworkers/models/openai_gpt_image.rb
|
159
162
|
- lib/oxaiworkers/models/openai_max.rb
|
160
163
|
- lib/oxaiworkers/models/openai_mini.rb
|
161
164
|
- lib/oxaiworkers/models/openai_nano.rb
|
165
|
+
- lib/oxaiworkers/models/stability_images.rb
|
162
166
|
- lib/oxaiworkers/module_request.rb
|
163
167
|
- lib/oxaiworkers/present_compat.rb
|
164
168
|
- lib/oxaiworkers/request.rb
|