ox-ai-workers 0.5.4 → 0.5.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 +7 -0
- data/README.md +18 -5
- data/exe/start +4 -0
- data/lib/ox-ai-workers.rb +3 -2
- data/lib/oxaiworkers/assistant/coder.rb +2 -0
- data/lib/oxaiworkers/assistant/localizer.rb +2 -0
- data/lib/oxaiworkers/assistant/module_base.rb +2 -0
- data/lib/oxaiworkers/assistant/sysop.rb +3 -1
- data/lib/oxaiworkers/iterator.rb +43 -24
- data/lib/oxaiworkers/load_i18n.rb +15 -0
- data/lib/oxaiworkers/tool/database.rb +27 -22
- data/lib/oxaiworkers/tool/eval.rb +17 -10
- data/lib/oxaiworkers/tool/file_system.rb +31 -26
- data/lib/oxaiworkers/tool_definition.rb +10 -2
- data/lib/oxaiworkers/version.rb +1 -1
- data/template/my_assistant.rb +6 -0
- data/template/tools/my_tool.rb +13 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ca54c1ff9c1f4360ddfe986c4b5bc6fb6b7c0cde0484d1b2f88bfe4d8c5707b7
|
4
|
+
data.tar.gz: 2c54e55fedd99af36f7a510ab923c54581faecfc8b36caa4d228f14349e293a8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b8915a64826c118706328c89a87c01fdf49f13b63408c64d5af1ea53a2f92dbb326b9e537f36aa755297a5c919239d426da1f38a83b3cd5fdfbc5a9ebc4146f7
|
7
|
+
data.tar.gz: 8614ed16d7771b594bda52de36f87bbd211adfc8c579fff752634fc4ce44a7d554cd25cf7b32bfaa80954830f835a7b3c1f61d0e237c930bc043f433e98534c1
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.5.5] - 2024-08-02
|
4
|
+
|
5
|
+
- Added `only` for Tools
|
6
|
+
- Addded `locale` for `Iterator` and `Assistant`
|
7
|
+
|
8
|
+
## [0.5.4] - 2024-08-01
|
9
|
+
|
3
10
|
- def_except and def_only for `Iterator`
|
4
11
|
- Renamed on_pack_history to on_summarize
|
5
12
|
- Renamed all "pack_history" to "summarize"
|
data/README.md
CHANGED
@@ -63,7 +63,7 @@ worker = OxAiWorkers::Request.new(
|
|
63
63
|
temperature: 0.7 )
|
64
64
|
|
65
65
|
# Initialize a tool
|
66
|
-
my_tool = OxAiWorkers::Tool::Eval.new()
|
66
|
+
my_tool = OxAiWorkers::Tool::Eval.new(only: :sh)
|
67
67
|
|
68
68
|
# Create an iterator with the worker and tool
|
69
69
|
iterator = OxAiWorkers::Iterator.new(
|
@@ -86,9 +86,9 @@ For a more robust setup, you can configure the gem with your API keys, for examp
|
|
86
86
|
OxAiWorkers.configure do |config|
|
87
87
|
config.access_token = ENV.fetch("OPENAI")
|
88
88
|
config.model = "gpt-4o"
|
89
|
-
config.max_tokens = 4096
|
90
|
-
config.temperature = 0.7
|
91
|
-
config.auto_execute = true
|
89
|
+
config.max_tokens = 4096 # Default
|
90
|
+
config.temperature = 0.7 # Default
|
91
|
+
config.auto_execute = true # Default
|
92
92
|
end
|
93
93
|
```
|
94
94
|
|
@@ -102,11 +102,20 @@ assistant.task = "Remove all cron jobs."
|
|
102
102
|
assistant.add_response("blah-blah-blah")
|
103
103
|
```
|
104
104
|
|
105
|
+
Besides, you can create assistants with different locales
|
106
|
+
|
107
|
+
```ruby
|
108
|
+
I18n.with_locale(:en) { @sysop_en = OxAiWorkers::Assistant::Sysop.new() }
|
109
|
+
|
110
|
+
# Assign tasks and responses in different languages
|
111
|
+
@sysop_en.task = "Remove all cron jobs."
|
112
|
+
```
|
113
|
+
|
105
114
|
Or you can create a lower-level iterator for more control:
|
106
115
|
|
107
116
|
```ruby
|
108
117
|
my_worker = OxAiWorkers::Request.new
|
109
|
-
my_tool = OxAiWorkers::Tool::Eval.new
|
118
|
+
my_tool = OxAiWorkers::Tool::Eval.new(only: [:sh])
|
110
119
|
|
111
120
|
iterator = OxAiWorkers::Iterator.new(
|
112
121
|
worker: my_worker,
|
@@ -135,10 +144,14 @@ steps << 'Step 3. Call the necessary functions one after another until the desir
|
|
135
144
|
steps << "Step 4. When all intermediate steps are completed and the exact content of previous messages is no longer relevant, use the #{OxAiWorkers::Iterator.full_function_name(:summarize)} function."
|
136
145
|
steps << "Step 5. When the solution is ready, notify about it and wait for the user's response."
|
137
146
|
|
147
|
+
# To retain the locale if you have assistants in different languages in your project.
|
148
|
+
store_locale # Optional
|
149
|
+
|
138
150
|
@iterator = OxAiWorkers::Iterator.new(
|
139
151
|
worker: init_worker(delayed: delayed, model: model),
|
140
152
|
role: 'You are a software agent inside my computer',
|
141
153
|
tools: [MyTool.new],
|
154
|
+
locale: @locale || I18n.locale,
|
142
155
|
steps: steps,
|
143
156
|
# def_except: [:summarize], # It's except steps with that functions
|
144
157
|
# def_only: [:inner_monologue, :outer_voice], # Use it only with your steps
|
data/exe/start
CHANGED
data/lib/ox-ai-workers.rb
CHANGED
@@ -11,13 +11,14 @@ require_relative 'oxaiworkers/version'
|
|
11
11
|
require_relative 'oxaiworkers/contextual_logger'
|
12
12
|
require_relative 'oxaiworkers/load_i18n'
|
13
13
|
require_relative 'oxaiworkers/present_compat'
|
14
|
+
require_relative 'oxaiworkers/tool_definition'
|
15
|
+
require_relative 'oxaiworkers/dependency_helper'
|
16
|
+
|
14
17
|
require_relative 'oxaiworkers/module_request'
|
15
18
|
require_relative 'oxaiworkers/state_helper'
|
16
19
|
require_relative 'oxaiworkers/state_batch'
|
17
20
|
require_relative 'oxaiworkers/state_tools'
|
18
|
-
require_relative 'oxaiworkers/tool_definition'
|
19
21
|
require_relative 'oxaiworkers/delayed_request'
|
20
|
-
require_relative 'oxaiworkers/dependency_helper'
|
21
22
|
require_relative 'oxaiworkers/iterator'
|
22
23
|
require_relative 'oxaiworkers/request'
|
23
24
|
|
@@ -6,10 +6,12 @@ module OxAiWorkers
|
|
6
6
|
include OxAiWorkers::Assistant::ModuleBase
|
7
7
|
|
8
8
|
def initialize(delayed: false, model: nil, language: 'ruby')
|
9
|
+
store_locale
|
9
10
|
@iterator = Iterator.new(
|
10
11
|
worker: init_worker(delayed: delayed, model: model),
|
11
12
|
role: format(I18n.t('oxaiworkers.assistant.coder.role'), language),
|
12
13
|
tools: [Tool::Eval.new, Tool::FileSystem.new],
|
14
|
+
locale: @locale,
|
13
15
|
on_inner_monologue: ->(text:) { puts "monologue: #{text}".colorize(:yellow) },
|
14
16
|
on_outer_voice: ->(text:) { puts "voice: #{text}".colorize(:green) },
|
15
17
|
on_action_request: ->(text:) { puts "action: #{text}".colorize(:red) },
|
@@ -6,10 +6,12 @@ module OxAiWorkers
|
|
6
6
|
include OxAiWorkers::Assistant::ModuleBase
|
7
7
|
|
8
8
|
def initialize(delayed: false, model: nil, language: 'русский', locale: :ru, source: 'english')
|
9
|
+
store_locale
|
9
10
|
@iterator = Iterator.new(
|
10
11
|
worker: init_worker(delayed: delayed, model: model),
|
11
12
|
role: format(I18n.t('oxaiworkers.assistant.localizer.role'), language),
|
12
13
|
tools: [Tool::Eval.new, Tool::FileSystem.new],
|
14
|
+
locale: @locale,
|
13
15
|
on_inner_monologue: ->(text:) { puts "monologue: #{text}".colorize(:yellow) },
|
14
16
|
on_outer_voice: ->(text:) { puts "voice: #{text}".colorize(:green) },
|
15
17
|
on_action_request: ->(text:) { puts "action: #{text}".colorize(:red) },
|
@@ -6,10 +6,12 @@ module OxAiWorkers
|
|
6
6
|
include OxAiWorkers::Assistant::ModuleBase
|
7
7
|
|
8
8
|
def initialize(delayed: false, model: nil)
|
9
|
+
store_locale
|
9
10
|
@iterator = Iterator.new(
|
10
11
|
worker: init_worker(delayed: delayed, model: model),
|
11
12
|
role: I18n.t('oxaiworkers.assistant.sysop.role'),
|
12
|
-
tools: [Tool::Eval.new],
|
13
|
+
tools: [Tool::Eval.new(only: :sh), Tool::FileSystem.new(only: %i[read_file write_to_file])],
|
14
|
+
locale: @locale,
|
13
15
|
on_inner_monologue: ->(text:) { puts "monologue: #{text}".colorize(:yellow) },
|
14
16
|
on_outer_voice: ->(text:) { puts "voice: #{text}".colorize(:green) },
|
15
17
|
on_action_request: ->(text:) { puts "action: #{text}".colorize(:red) },
|
data/lib/oxaiworkers/iterator.rb
CHANGED
@@ -4,37 +4,45 @@ module OxAiWorkers
|
|
4
4
|
class Iterator < OxAiWorkers::StateTools
|
5
5
|
ITERATOR_FUNCTIONS = %i[inner_monologue outer_voice action_request summarize].freeze
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
attr_accessor :on_inner_monologue, :on_outer_voice, :on_action_request, :on_summarize, :def_except, :def_only
|
7
|
+
include OxAiWorkers::ToolDefinition
|
8
|
+
include OxAiWorkers::LoadI18n
|
10
9
|
|
11
|
-
|
12
|
-
|
13
|
-
required: true
|
14
|
-
end
|
10
|
+
attr_accessor :worker, :role, :messages, :context, :result, :tools, :queue, :monologue, :tasks, :milestones,
|
11
|
+
:on_inner_monologue, :on_outer_voice, :on_action_request, :on_summarize, :def_except, :def_only
|
15
12
|
|
16
|
-
|
17
|
-
|
18
|
-
end
|
13
|
+
def initialize(worker:, role: nil, tools: [], on_inner_monologue: nil, on_outer_voice: nil, on_action_request: nil,
|
14
|
+
on_summarize: nil, steps: nil, def_except: [], def_only: nil, locale: nil)
|
19
15
|
|
20
|
-
|
21
|
-
property :action, type: 'string', description: I18n.t('oxaiworkers.iterator.action_request.action'),
|
22
|
-
required: true
|
23
|
-
end
|
16
|
+
@locale = locale || I18n.locale
|
24
17
|
|
25
|
-
|
26
|
-
|
27
|
-
|
18
|
+
with_locale do
|
19
|
+
define_function :inner_monologue, description: I18n.t('oxaiworkers.iterator.inner_monologue.description') do
|
20
|
+
property :speach, type: 'string', description: I18n.t('oxaiworkers.iterator.inner_monologue.speach'),
|
21
|
+
required: true
|
22
|
+
end
|
23
|
+
|
24
|
+
define_function :outer_voice, description: I18n.t('oxaiworkers.iterator.outer_voice.description') do
|
25
|
+
property :text, type: 'string', description: I18n.t('oxaiworkers.iterator.outer_voice.text'), required: true
|
26
|
+
end
|
27
|
+
|
28
|
+
define_function :action_request, description: I18n.t('oxaiworkers.iterator.action_request.description') do
|
29
|
+
property :action, type: 'string', description: I18n.t('oxaiworkers.iterator.action_request.action'),
|
30
|
+
required: true
|
31
|
+
end
|
32
|
+
|
33
|
+
define_function :summarize, description: I18n.t('oxaiworkers.iterator.summarize.description') do
|
34
|
+
property :text, type: 'string', description: I18n.t('oxaiworkers.iterator.summarize.text'), required: true
|
35
|
+
end
|
36
|
+
|
37
|
+
@monologue = steps || I18n.t('oxaiworkers.iterator.monologue')
|
38
|
+
end
|
28
39
|
|
29
|
-
def initialize(worker:, role: nil, tools: [], on_inner_monologue: nil, on_outer_voice: nil, on_action_request: nil,
|
30
|
-
on_summarize: nil, steps: nil, def_except: [], def_only: nil)
|
31
40
|
@worker = worker
|
32
41
|
@tools = tools
|
33
42
|
@role = role
|
34
43
|
@context = []
|
35
44
|
@def_only = def_only || ITERATOR_FUNCTIONS
|
36
45
|
@def_except = def_except
|
37
|
-
@monologue = steps || I18n.t('oxaiworkers.iterator.monologue')
|
38
46
|
|
39
47
|
@on_inner_monologue = on_inner_monologue
|
40
48
|
@on_outer_voice = on_outer_voice
|
@@ -82,7 +90,9 @@ module OxAiWorkers
|
|
82
90
|
def summarize(text:)
|
83
91
|
@milestones << text.to_s
|
84
92
|
@messages = []
|
85
|
-
|
93
|
+
with_locale do
|
94
|
+
@queue << { role: :assistant, content: I18n.t('oxaiworkers.iterator.summarize.result') }
|
95
|
+
end
|
86
96
|
@worker.finish
|
87
97
|
rebuild_worker
|
88
98
|
complete! if can_complete?
|
@@ -103,8 +113,16 @@ module OxAiWorkers
|
|
103
113
|
@tasks.each { |task| @worker.append(role: :user, content: task) }
|
104
114
|
@milestones.each { |milestone| @worker.append(role: :assistant, content: milestone) }
|
105
115
|
@worker.append(messages: @messages)
|
106
|
-
@worker.tools =
|
107
|
-
|
116
|
+
@worker.tools = function_schemas.to_openai_format(only: available_defs)
|
117
|
+
return unless @tools.present?
|
118
|
+
|
119
|
+
@worker.tools += @tools.map do |tool|
|
120
|
+
if tool.respond_to?(:function_schemas)
|
121
|
+
tool.function_schemas.to_openai_format
|
122
|
+
else
|
123
|
+
tool.class.function_schemas.to_openai_format
|
124
|
+
end
|
125
|
+
end.flatten
|
108
126
|
end
|
109
127
|
|
110
128
|
def available_defs
|
@@ -138,7 +156,8 @@ module OxAiWorkers
|
|
138
156
|
@queue << { role: :assistant, content: @worker.tool_calls_raw.to_s }
|
139
157
|
@worker.tool_calls.each do |external_call|
|
140
158
|
tool = ([self] + @tools).select do |t|
|
141
|
-
|
159
|
+
tool_name = t.respond_to?(:tool_name) ? t.tool_name : t.class.tool_name
|
160
|
+
tool_name == external_call[:class] && t.respond_to?(external_call[:name])
|
142
161
|
end.first
|
143
162
|
unless tool.nil?
|
144
163
|
out = tool.send(external_call[:name], **external_call[:args])
|
@@ -2,3 +2,18 @@
|
|
2
2
|
|
3
3
|
require 'i18n'
|
4
4
|
I18n.load_path += Dir["#{File.expand_path('../../locales', __dir__)}/*.yml"]
|
5
|
+
|
6
|
+
module OxAiWorkers
|
7
|
+
module LoadI18n
|
8
|
+
attr_accessor :locale
|
9
|
+
|
10
|
+
def with_locale(&action)
|
11
|
+
# locale = respond_to?(:locale) ? self.locale : OxAiWorkers.configuration.locale
|
12
|
+
I18n.with_locale(@locale, &action)
|
13
|
+
end
|
14
|
+
|
15
|
+
def store_locale
|
16
|
+
@locale = I18n.locale
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -10,28 +10,9 @@ module OxAiWorkers
|
|
10
10
|
# database = OxAiWorkers::Tool::Database.new(connection_string: "postgres://user:password@localhost:5432/db_name")
|
11
11
|
#
|
12
12
|
class Database
|
13
|
-
|
13
|
+
include OxAiWorkers::ToolDefinition
|
14
14
|
include OxAiWorkers::DependencyHelper
|
15
|
-
|
16
|
-
define_function :list_tables,
|
17
|
-
description: I18n.t('oxaiworkers.tool.database_tool.list_tables.description')
|
18
|
-
|
19
|
-
define_function :describe_tables,
|
20
|
-
description: I18n.t('oxaiworkers.tool.database_tool.describe_tables.description') do
|
21
|
-
property :tables, type: 'string',
|
22
|
-
description: I18n.t('oxaiworkers.tool.database_tool.describe_tables.tables'),
|
23
|
-
required: true
|
24
|
-
end
|
25
|
-
|
26
|
-
define_function :dump_schema,
|
27
|
-
description: I18n.t('oxaiworkers.tool.database_tool.dump_schema.description')
|
28
|
-
|
29
|
-
define_function :execute,
|
30
|
-
description: I18n.t('oxaiworkers.tool.database_tool.execute.description') do
|
31
|
-
property :input, type: 'string',
|
32
|
-
description: I18n.t('oxaiworkers.tool.database_tool.execute.input'),
|
33
|
-
required: true
|
34
|
-
end
|
15
|
+
include OxAiWorkers::LoadI18n
|
35
16
|
|
36
17
|
attr_reader :db, :requested_tables, :excluded_tables
|
37
18
|
|
@@ -41,11 +22,35 @@ module OxAiWorkers
|
|
41
22
|
# @param tables [Array<Symbol>] The tables to use. Will use all if empty.
|
42
23
|
# @param except_tables [Array<Symbol>] The tables to exclude. Will exclude none if empty.
|
43
24
|
# @return [Database] Database object
|
44
|
-
def initialize(connection_string:, tables: [], exclude_tables: [])
|
25
|
+
def initialize(connection_string:, tables: [], exclude_tables: [], only: nil)
|
45
26
|
depends_on 'sequel'
|
46
27
|
|
47
28
|
raise StandardError, 'connection_string parameter cannot be blank' if connection_string.empty?
|
48
29
|
|
30
|
+
store_locale
|
31
|
+
|
32
|
+
init_white_list_with only
|
33
|
+
|
34
|
+
define_function :list_tables,
|
35
|
+
description: I18n.t('oxaiworkers.tool.database_tool.list_tables.description')
|
36
|
+
|
37
|
+
define_function :describe_tables,
|
38
|
+
description: I18n.t('oxaiworkers.tool.database_tool.describe_tables.description') do
|
39
|
+
property :tables, type: 'string',
|
40
|
+
description: I18n.t('oxaiworkers.tool.database_tool.describe_tables.tables'),
|
41
|
+
required: true
|
42
|
+
end
|
43
|
+
|
44
|
+
define_function :dump_schema,
|
45
|
+
description: I18n.t('oxaiworkers.tool.database_tool.dump_schema.description')
|
46
|
+
|
47
|
+
define_function :execute,
|
48
|
+
description: I18n.t('oxaiworkers.tool.database_tool.execute.description') do
|
49
|
+
property :input, type: 'string',
|
50
|
+
description: I18n.t('oxaiworkers.tool.database_tool.execute.input'),
|
51
|
+
required: true
|
52
|
+
end
|
53
|
+
|
49
54
|
@db = Sequel.connect(connection_string)
|
50
55
|
@requested_tables = tables
|
51
56
|
@excluded_tables = exclude_tables
|
@@ -5,21 +5,28 @@ require 'open3'
|
|
5
5
|
module OxAiWorkers
|
6
6
|
module Tool
|
7
7
|
class Eval
|
8
|
-
|
8
|
+
include OxAiWorkers::ToolDefinition
|
9
9
|
include OxAiWorkers::DependencyHelper
|
10
|
+
include OxAiWorkers::LoadI18n
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
# end
|
12
|
+
def initialize(only: nil)
|
13
|
+
store_locale
|
14
14
|
|
15
|
-
|
16
|
-
|
15
|
+
init_white_list_with only
|
16
|
+
|
17
|
+
define_function :ruby, description: I18n.t('oxaiworkers.tool.eval.ruby.description') do
|
18
|
+
property :input, type: 'string', description: I18n.t('oxaiworkers.tool.eval.ruby.input'), required: true
|
19
|
+
end
|
20
|
+
|
21
|
+
define_function :sh, description: I18n.t('oxaiworkers.tool.eval.sh.description') do
|
22
|
+
property :input, type: 'string', description: I18n.t('oxaiworkers.tool.eval.sh.input'), required: true
|
23
|
+
end
|
17
24
|
end
|
18
25
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
26
|
+
def ruby(input:)
|
27
|
+
puts "Executing ruby: \"#{input}\"".colorize(:red)
|
28
|
+
eval(input)
|
29
|
+
end
|
23
30
|
|
24
31
|
def sh(input:)
|
25
32
|
OxAiWorkers.logger.info("Executing sh: \"#{input}\"", for: self.class)
|
@@ -11,30 +11,35 @@ module OxAiWorkers
|
|
11
11
|
# file_system = OxAiWorkers::Tool::FileSystem.new
|
12
12
|
#
|
13
13
|
class FileSystem
|
14
|
-
|
14
|
+
include OxAiWorkers::ToolDefinition
|
15
15
|
include OxAiWorkers::DependencyHelper
|
16
|
+
include OxAiWorkers::LoadI18n
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
property :directory_path, type: 'string',
|
20
|
-
description: I18n.t('oxaiworkers.tool.file_system.list_directory.directory_path'),
|
21
|
-
required: true
|
22
|
-
end
|
18
|
+
def initialize(only: nil)
|
19
|
+
depends_on 'ptools'
|
23
20
|
|
24
|
-
|
25
|
-
property :file_path, type: 'string', description: I18n.t('oxaiworkers.tool.file_system.read_file.file_path'),
|
26
|
-
required: true
|
27
|
-
end
|
21
|
+
store_locale
|
28
22
|
|
29
|
-
|
30
|
-
property :file_path, type: 'string',
|
31
|
-
description: I18n.t('oxaiworkers.tool.file_system.write_to_file.file_path'), required: true
|
32
|
-
property :content, type: 'string', description: I18n.t('oxaiworkers.tool.file_system.write_to_file.content'),
|
33
|
-
required: true
|
34
|
-
end
|
23
|
+
init_white_list_with only
|
35
24
|
|
36
|
-
|
37
|
-
|
25
|
+
define_function :list_directory,
|
26
|
+
description: I18n.t('oxaiworkers.tool.file_system.list_directory.description') do
|
27
|
+
property :directory_path, type: 'string',
|
28
|
+
description: I18n.t('oxaiworkers.tool.file_system.list_directory.directory_path'),
|
29
|
+
required: true
|
30
|
+
end
|
31
|
+
|
32
|
+
define_function :read_file, description: I18n.t('oxaiworkers.tool.file_system.read_file.description') do
|
33
|
+
property :file_path, type: 'string', description: I18n.t('oxaiworkers.tool.file_system.read_file.file_path'),
|
34
|
+
required: true
|
35
|
+
end
|
36
|
+
|
37
|
+
define_function :write_to_file, description: I18n.t('oxaiworkers.tool.file_system.write_to_file.description') do
|
38
|
+
property :file_path, type: 'string',
|
39
|
+
description: I18n.t('oxaiworkers.tool.file_system.write_to_file.file_path'), required: true
|
40
|
+
property :content, type: 'string', description: I18n.t('oxaiworkers.tool.file_system.write_to_file.content'),
|
41
|
+
required: true
|
42
|
+
end
|
38
43
|
end
|
39
44
|
|
40
45
|
def list_directory(directory_path:)
|
@@ -42,31 +47,31 @@ module OxAiWorkers
|
|
42
47
|
list = Dir.entries(directory_path)
|
43
48
|
list.delete_if { |f| f.start_with?('.') }
|
44
49
|
if list.present?
|
45
|
-
"Contents of directory \"#{directory_path}\":\n #{list.join("\n")}"
|
50
|
+
with_locale { "Contents of directory \"#{directory_path}\":\n #{list.join("\n")}" }
|
46
51
|
else
|
47
|
-
"Directory is empty: #{directory_path}"
|
52
|
+
with_locale { "Directory is empty: #{directory_path}" }
|
48
53
|
end
|
49
54
|
rescue Errno::ENOENT
|
50
|
-
"No such directory: #{directory_path}"
|
55
|
+
with_locale { "No such directory: #{directory_path}" }
|
51
56
|
end
|
52
57
|
|
53
58
|
def read_file(file_path:)
|
54
59
|
OxAiWorkers.logger.info("Reading file: #{file_path}", for: self.class)
|
55
60
|
if File.binary?(file_path)
|
56
|
-
"File is binary: #{file_path}"
|
61
|
+
with_locale { "File is binary: #{file_path}" }
|
57
62
|
else
|
58
63
|
File.read(file_path).to_s
|
59
64
|
end
|
60
65
|
rescue Errno::ENOENT
|
61
|
-
"No such file: #{file_path}"
|
66
|
+
with_locale { "No such file: #{file_path}" }
|
62
67
|
end
|
63
68
|
|
64
69
|
def write_to_file(file_path:, content:)
|
65
70
|
OxAiWorkers.logger.info("Writing to file: #{file_path}", for: self.class)
|
66
71
|
File.write(file_path, content)
|
67
|
-
"Content was successfully written to the file: #{file_path}"
|
72
|
+
with_locale { "Content was successfully written to the file: #{file_path}" }
|
68
73
|
rescue Errno::EACCES
|
69
|
-
"Permission denied: #{file_path}"
|
74
|
+
with_locale { "Permission denied: #{file_path}" }
|
70
75
|
end
|
71
76
|
end
|
72
77
|
end
|
@@ -37,13 +37,21 @@ require "json"
|
|
37
37
|
# end
|
38
38
|
#
|
39
39
|
module OxAiWorkers::ToolDefinition
|
40
|
+
attr_accessor :white_list
|
41
|
+
|
42
|
+
def init_white_list_with only
|
43
|
+
@white_list = only.is_a?(Array) ? only : [only]
|
44
|
+
end
|
45
|
+
|
40
46
|
# Defines a function for the tool
|
41
47
|
#
|
42
48
|
# @param method_name [Symbol] Name of the method to define
|
43
49
|
# @param description [String] Description of the function
|
44
50
|
# @yield Block that defines the parameters for the function
|
45
51
|
def define_function(method_name, description:, &)
|
46
|
-
|
52
|
+
if @white_list.nil? || @white_list == method_name || @white_list.include?(method_name)
|
53
|
+
function_schemas.add_function(method_name:, description:, &)
|
54
|
+
end
|
47
55
|
end
|
48
56
|
|
49
57
|
# Returns the FunctionSchemas instance for this tool
|
@@ -57,7 +65,7 @@ module OxAiWorkers::ToolDefinition
|
|
57
65
|
#
|
58
66
|
# @return [String] The snake_case version of the class name
|
59
67
|
def tool_name
|
60
|
-
@tool_name ||= name
|
68
|
+
@tool_name ||= (self.respond_to?(:name) ? name : self.class.name)
|
61
69
|
.gsub("::", "_")
|
62
70
|
.gsub(/(?<=[A-Z])(?=[A-Z][a-z])|(?<=[a-z\d])(?=[A-Z])/, "_")
|
63
71
|
.downcase
|
data/lib/oxaiworkers/version.rb
CHANGED
data/template/my_assistant.rb
CHANGED
@@ -15,11 +15,17 @@ class MyAssistant
|
|
15
15
|
# steps << "Step 4. When all intermediate steps are completed and the exact content of previous messages is no longer relevant, use the #{OxAiWorkers::Iterator.full_function_name(:summarize)} function."
|
16
16
|
# steps << "Step 5. When the solution is ready, notify about it and wait for the user's response."
|
17
17
|
|
18
|
+
# To retain the locale if you have assistants in different languages in your project.
|
19
|
+
# store_locale # Optional
|
20
|
+
|
18
21
|
@iterator = OxAiWorkers::Iterator.new(
|
19
22
|
worker: init_worker(delayed: delayed, model: model),
|
20
23
|
role: 'You are a software agent inside my computer',
|
21
24
|
tools: [MyTool.new],
|
25
|
+
# locale: @locale || I18n.locale,
|
22
26
|
# steps: steps,
|
27
|
+
# def_except: [:summarize], # It's except steps with that functions
|
28
|
+
# def_only: [:inner_monologue, :outer_voice], # Use it only with your steps
|
23
29
|
on_inner_monologue: ->(text:) { puts "monologue: #{text}".colorize(:yellow) },
|
24
30
|
on_outer_voice: ->(text:) { puts "voice: #{text}".colorize(:green) },
|
25
31
|
on_action_request: ->(text:) { puts "action: #{text}".colorize(:red) },
|
data/template/tools/my_tool.rb
CHANGED
@@ -1,13 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class MyTool
|
4
|
-
extend OxAiWorkers::ToolDefinition
|
5
|
-
include OxAiWorkers::DependencyHelper
|
4
|
+
extend OxAiWorkers::ToolDefinition # (!) extend
|
6
5
|
|
7
6
|
define_function :sh, description: 'Execute a sh command and get the result (stdout + stderr)' do
|
8
7
|
property :input, type: 'string', description: 'Source command', required: true
|
9
8
|
end
|
10
9
|
|
10
|
+
# Alternative implementation if you need to filter functions during initialization.
|
11
|
+
# include OxAiWorkers::ToolDefinition # (!) include
|
12
|
+
# include OxAiWorkers::LoadI18n # to support multiple languages
|
13
|
+
#
|
14
|
+
# def initialize(only: nil)
|
15
|
+
# store_locale # To retain the locale if you have MyTool in different languages.
|
16
|
+
# init_white_list_with only
|
17
|
+
# define_function :sh, description: I18n.t('Execute a sh command and get the result (stdout + stderr)') do
|
18
|
+
# property :input, type: 'string', description: I18n.t('Source command'), required: true
|
19
|
+
# end
|
20
|
+
# end
|
21
|
+
|
11
22
|
def sh(input:)
|
12
23
|
OxAiWorkers.logger.info("Executing sh: \"#{input}\"", for: self.class)
|
13
24
|
stdout_and_stderr_s, = Open3.capture2e(input)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ox-ai-workers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Denis Smolev
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-08-
|
11
|
+
date: 2024-08-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colorize
|