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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b0e2cfa9b2f611dc00729dfff984e91b4b3977703d91f360f80ff4625013cccc
4
- data.tar.gz: fe2e37c5fc822a1a661f36b421f511f24c4979962ab4d67e79912d0101ace732
3
+ metadata.gz: c008f2f4f413251ffa88e00935e118c9844b2e67ab5088ca1091f2b7ac64ac77
4
+ data.tar.gz: a9b4cf53a19322a10db55ffa480d1e9bfe3a587411398ca5797058f5941c6ee8
5
5
  SHA512:
6
- metadata.gz: ab9b3e707484c1607ad46ba9cecaedc19d9e673aa4e3a17564402e5b80e8d63617a62842176eb01aea46e29e98b9b2c6e63861cb5ad82470581fc2ba379606a6
7
- data.tar.gz: ceba0647dbbcc2a1cde6b34963d7f3a7f6d9d0c299826bd06891c03d6501c3edb6f3e9eecc3f84c155f61bc70deb613897c8c6ae7e62c41084784b3e5688c0b8
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: [MyTool.new],
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. If a file name is provided, the image will be saved in png format. In any case, the url of the generated image will be returned.'
44
- prompt: 'Text description of the image to generate'
45
- size: 'Size of the generated image (1024x1792, 1792x1024, 1024x1024)'
46
- quality: 'Quality of the generated image (standard, hd)'
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: 'Инструмент генерации изображений: Создает изображение на основе предоставленного текстового запроса. Если указать имя файла, изображение будет сохранено в формате png. В любом случае будет возвращен url изображения.'
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: 'Инструмент редактирования изображений: Редактирует изображение на основе предоставленного текстового запроса. Если указать имя файла, изображение будет сохранено в формате png. В любом случае будет возвращен url изображения.'
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/module_base'
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: init_worker(delayed:, model:),
24
+ worker:,
22
25
  role: @role,
23
- tools: [Tool::Pixels.new(worker: init_worker(delayed: false, model:), current_dir:)],
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) }
@@ -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/'
@@ -0,0 +1,11 @@
1
+ module OxAiWorkers
2
+ module Models
3
+ class ImagesBase
4
+ attr_accessor :client, :options, :qualities, :sizes, :result
5
+
6
+ def initialize(options:)
7
+ @options = options
8
+ end
9
+ end
10
+ end
11
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module OxAiWorkers
4
4
  module Models
5
- module ModuleBase
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, :on_stream_proc
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
- parameters[:tool_choice] = 'required'
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, :url, :current_dir, :image_model, :mask
12
-
13
- MODELS = {
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
- property :size, type: 'string', description: I18n.t('oxaiworkers.tool.pixels.generate_image.size'),
35
- enum: MODELS[image_model]['size']
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
- property :quality, type: 'string', description: I18n.t('oxaiworkers.tool.pixels.generate_image.quality'),
42
- enum: MODELS[image_model]['quality']
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
- puts "generate_image: #{prompt}"
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
- "url: #{@url}\nfile_name: #{path}\n\nrevised_prompt: #{revised_prompt}"
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
- "url: #{@url}\n\nrevised_prompt: #{revised_prompt}"
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(URI.open(@url).read)
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module OxAiWorkers
4
- VERSION = '0.9.3.1'
4
+ VERSION = '0.9.5'
5
5
  end
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.3.1
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/module_base.rb
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