foobara-agent 0.0.13 → 0.0.14
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 +4 -0
- data/src/foobara/agent/accomplish_goal.rb +19 -5
- data/src/foobara/agent/determine_base.rb +13 -27
- data/src/foobara/agent/determine_next_command_name_and_inputs.rb +42 -0
- data/src/foobara/agent.rb +16 -15
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dc32aeaa66ec947920e085944f7948d22d97b4fa3b39d1a4b4fbf58755ca4321
|
4
|
+
data.tar.gz: 0dc7b3d02061bf0a615ab6299ea5f607fff1d703804d5368b57a9157d4edf64a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e1a1d3780d7a3112cff93e7e626ec677ad558ce605e65c60f00ec3b8213b604e248ca4428311303b1902451f2bcc7d2a5f17f3725dde77bbb4725aeb10b9898d
|
7
|
+
data.tar.gz: f6113517024dc34e999fafcb3bc5ee0ec98fb63628f61725b5631e454d6edd4714933a745232e57f2a1c8f686f0d2544b481b1726cfff3e4dbbc47666bdd74c4
|
data/CHANGELOG.md
CHANGED
@@ -19,7 +19,6 @@ module Foobara
|
|
19
19
|
io_out :duck
|
20
20
|
io_err :duck
|
21
21
|
agent Agent, :required
|
22
|
-
context Context, :required, "The current context of the agent"
|
23
22
|
maximum_command_calls :integer,
|
24
23
|
:allow_nil,
|
25
24
|
default: 25,
|
@@ -30,7 +29,9 @@ module Foobara
|
|
30
29
|
default: "claude-3-7-sonnet-20250219",
|
31
30
|
description: "The model to use for the LLM"
|
32
31
|
max_llm_calls_per_minute :integer, :allow_nil
|
33
|
-
|
32
|
+
user_association_depth :symbol, :allow_nil, one_of: Foobara::AssociationDepth
|
33
|
+
result_entity_depth :symbol, :allow_nil, one_of: Foobara::AssociationDepth
|
34
|
+
pass_aggregates_to_llm :boolean, :allow_nil
|
34
35
|
end
|
35
36
|
|
36
37
|
result do
|
@@ -41,8 +42,10 @@ module Foobara
|
|
41
42
|
depends_on ListCommands
|
42
43
|
|
43
44
|
def execute
|
44
|
-
|
45
|
-
|
45
|
+
unless list_commands_already_ran?
|
46
|
+
simulate_describe_list_commands_command
|
47
|
+
simulate_list_commands_run
|
48
|
+
end
|
46
49
|
# simulate_describe_command_run_for_all_commands
|
47
50
|
|
48
51
|
until mission_accomplished or given_up
|
@@ -68,6 +71,10 @@ module Foobara
|
|
68
71
|
:final_result, :final_message, :command_response, :delayed_command_name,
|
69
72
|
:command_calls
|
70
73
|
|
74
|
+
def list_commands_already_ran?
|
75
|
+
context.command_log.any? { |log_entry| log_entry.command_name =~ /\bListCommands\z/ }
|
76
|
+
end
|
77
|
+
|
71
78
|
def simulate_list_commands_run
|
72
79
|
self.next_command_name = ListCommands.full_command_name
|
73
80
|
self.next_command_raw_inputs = nil
|
@@ -141,7 +148,10 @@ module Foobara
|
|
141
148
|
|
142
149
|
compact_command_log
|
143
150
|
|
144
|
-
inputs_for_determine = {
|
151
|
+
inputs_for_determine = { agent:, llm_model: }
|
152
|
+
unless pass_aggregates_to_llm.nil?
|
153
|
+
inputs_for_determine[:pass_aggregates_to_llm] = pass_aggregates_to_llm
|
154
|
+
end
|
145
155
|
determine_command = DetermineNextCommandNameAndInputs.new(inputs_for_determine)
|
146
156
|
|
147
157
|
outcome = begin
|
@@ -516,6 +526,10 @@ module Foobara
|
|
516
526
|
sleep seconds
|
517
527
|
end
|
518
528
|
end
|
529
|
+
|
530
|
+
def context
|
531
|
+
agent.context
|
532
|
+
end
|
519
533
|
end
|
520
534
|
end
|
521
535
|
end
|
@@ -2,9 +2,12 @@ require "foobara/llm_backed_command"
|
|
2
2
|
|
3
3
|
module Foobara
|
4
4
|
class Agent < CommandConnector
|
5
|
+
# TODO: just move this back to DetermineNextCommandAndInputs since it's now the only base class
|
5
6
|
class DetermineBase < Foobara::LlmBackedCommand
|
6
7
|
inputs do
|
7
|
-
|
8
|
+
pass_aggregates_to_llm :boolean, :allow_nil, "Should we send aggregates to the LLM or " \
|
9
|
+
"require it to fetch what it needs?"
|
10
|
+
agent Agent, :required
|
8
11
|
llm_model :string,
|
9
12
|
one_of: Foobara::Ai::AnswerBot::Types::ModelEnum,
|
10
13
|
default: "claude-3-7-sonnet-20250219",
|
@@ -12,7 +15,11 @@ module Foobara
|
|
12
15
|
end
|
13
16
|
|
14
17
|
def association_depth
|
15
|
-
|
18
|
+
if pass_aggregates_to_llm
|
19
|
+
Foobara::AssociationDepth::AGGREGATE
|
20
|
+
else
|
21
|
+
Foobara::AssociationDepth::ATOM
|
22
|
+
end
|
16
23
|
end
|
17
24
|
|
18
25
|
def build_messages
|
@@ -49,34 +56,13 @@ module Foobara
|
|
49
56
|
p
|
50
57
|
end
|
51
58
|
|
52
|
-
def llm_instructions
|
53
|
-
return @llm_instructions if defined?(@llm_instructions)
|
54
|
-
|
55
|
-
description = self.class.description
|
56
|
-
|
57
|
-
instructions = "You are the implementation of a command called #{self.class.scoped_full_name}"
|
58
|
-
|
59
|
-
instructions += if description && !description.empty?
|
60
|
-
" which has the following description:\n\n#{self.class.description}\n\n"
|
61
|
-
else
|
62
|
-
# :nocov:
|
63
|
-
". "
|
64
|
-
# :nocov:
|
65
|
-
end
|
66
|
-
|
67
|
-
instructions += "You are working towards accomplishing the following goal:\n\n#{goal}\n\n"
|
68
|
-
instructions += "Your response should match the following JSON schema: \n\n#{self.class.result_json_schema}\n\n"
|
69
|
-
instructions += "You can get more details about the result schema for a specific command by " \
|
70
|
-
"choosing the DescribeCommand command. " \
|
71
|
-
"You will reply with nothing more than the JSON you've generated so that the calling code " \
|
72
|
-
"can successfully parse your answer."
|
73
|
-
|
74
|
-
@llm_instructions = instructions
|
75
|
-
end
|
76
|
-
|
77
59
|
def goal
|
78
60
|
context.current_goal
|
79
61
|
end
|
62
|
+
|
63
|
+
def context
|
64
|
+
agent.context
|
65
|
+
end
|
80
66
|
end
|
81
67
|
end
|
82
68
|
end
|
@@ -3,6 +3,44 @@ require_relative "determine_base"
|
|
3
3
|
module Foobara
|
4
4
|
class Agent < CommandConnector
|
5
5
|
class DetermineNextCommandNameAndInputs < DetermineBase
|
6
|
+
class << self
|
7
|
+
def llm_instructions(assistant_association_depth, goal)
|
8
|
+
key = [assistant_association_depth, goal]
|
9
|
+
|
10
|
+
@llm_instructions_cache ||= {}
|
11
|
+
|
12
|
+
if @llm_instructions_cache.key?(key)
|
13
|
+
@llm_instructions_cache[key]
|
14
|
+
else
|
15
|
+
@llm_instructions_cache[key] = build_llm_instructions(assistant_association_depth, goal)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def build_llm_instructions(assistant_association_depth, goal)
|
20
|
+
instructions = "You are the implementation of a command called #{scoped_full_name}"
|
21
|
+
|
22
|
+
instructions += if description && !description.empty?
|
23
|
+
" which has the following description:\n\n#{description}\n\n"
|
24
|
+
else
|
25
|
+
# :nocov:
|
26
|
+
". "
|
27
|
+
# :nocov:
|
28
|
+
end
|
29
|
+
|
30
|
+
result_schema = result_json_schema(assistant_association_depth)
|
31
|
+
|
32
|
+
instructions += "You are working towards accomplishing the following goal:\n\n#{goal}\n\n"
|
33
|
+
instructions += "Your response of which command to run next should match the following JSON schema:"
|
34
|
+
instructions += "\n\n#{result_schema}\n\n"
|
35
|
+
instructions += "You can get more details about the inputs and result schemas for a specific command by " \
|
36
|
+
"choosing the DescribeCommand command. " \
|
37
|
+
"You will reply with nothing more than the JSON you've generated so that the calling code " \
|
38
|
+
"can successfully parse your answer."
|
39
|
+
|
40
|
+
instructions
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
6
44
|
description "Returns the name of the next command to run and its inputs given the progress " \
|
7
45
|
"towards accomplishing the current goal. " \
|
8
46
|
"If the goal has been accomplished it will choose the " \
|
@@ -12,6 +50,10 @@ module Foobara
|
|
12
50
|
command :string, :required
|
13
51
|
inputs :attributes, :allow_nil
|
14
52
|
end
|
53
|
+
|
54
|
+
def determine_llm_instructions
|
55
|
+
self.llm_instructions = self.class.llm_instructions(computed_user_association_depth, goal)
|
56
|
+
end
|
15
57
|
end
|
16
58
|
end
|
17
59
|
end
|
data/src/foobara/agent.rb
CHANGED
@@ -24,6 +24,7 @@ module Foobara
|
|
24
24
|
:io_out,
|
25
25
|
:io_err,
|
26
26
|
:max_llm_calls_per_minute,
|
27
|
+
:pass_aggregates_to_llm,
|
27
28
|
:result_entity_depth
|
28
29
|
|
29
30
|
def initialize(
|
@@ -38,6 +39,7 @@ module Foobara
|
|
38
39
|
io_err: nil,
|
39
40
|
max_llm_calls_per_minute: nil,
|
40
41
|
result_entity_depth: AssociationDepth::AGGREGATE,
|
42
|
+
pass_aggregates_to_llm: nil,
|
41
43
|
**opts
|
42
44
|
)
|
43
45
|
# TODO: shouldn't have to pass command_log here since it has a default, debug that
|
@@ -51,25 +53,21 @@ module Foobara
|
|
51
53
|
self.io_err = io_err
|
52
54
|
self.max_llm_calls_per_minute = max_llm_calls_per_minute
|
53
55
|
self.result_entity_depth = result_entity_depth
|
56
|
+
self.pass_aggregates_to_llm = pass_aggregates_to_llm
|
54
57
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
# end
|
58
|
+
pre_commit_transformer = if pass_aggregates_to_llm
|
59
|
+
CommandConnectors::Transformers::LoadAggregatesPreCommitTransformer
|
60
|
+
else
|
61
|
+
CommandConnectors::Transformers::LoadAtomsPreCommitTransformer
|
62
|
+
end
|
61
63
|
|
62
|
-
|
63
|
-
opts
|
64
|
-
|
65
|
-
|
66
|
-
end
|
64
|
+
opts = opts.merge(default_pre_commit_transformers: [
|
65
|
+
*opts[:default_pre_commit_transformers],
|
66
|
+
pre_commit_transformer
|
67
|
+
].uniq)
|
67
68
|
|
68
69
|
super(**opts)
|
69
70
|
|
70
|
-
# TODO: this should work now, switch to this approach
|
71
|
-
# add_default_inputs_transformer EntityToPrimaryKeyInputsTransformer
|
72
|
-
|
73
71
|
# TODO: push this convenience method up into base class?
|
74
72
|
command_classes&.each do |command_class|
|
75
73
|
connect(command_class)
|
@@ -171,7 +169,6 @@ module Foobara
|
|
171
169
|
inputs = {
|
172
170
|
goal:,
|
173
171
|
final_result_type: self.result_type,
|
174
|
-
context:,
|
175
172
|
agent: self
|
176
173
|
}
|
177
174
|
|
@@ -209,6 +206,10 @@ module Foobara
|
|
209
206
|
inputs[:result_entity_depth] = result_entity_depth
|
210
207
|
end
|
211
208
|
|
209
|
+
unless pass_aggregates_to_llm.nil?
|
210
|
+
inputs[:pass_aggregates_to_llm] = pass_aggregates_to_llm
|
211
|
+
end
|
212
|
+
|
212
213
|
inputs
|
213
214
|
end
|
214
215
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foobara-agent
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.14
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Miles Georgi
|
@@ -29,14 +29,14 @@ dependencies:
|
|
29
29
|
requirements:
|
30
30
|
- - "~>"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: 0.0
|
32
|
+
version: 1.0.0
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
35
|
version_requirements: !ruby/object:Gem::Requirement
|
36
36
|
requirements:
|
37
37
|
- - "~>"
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version: 0.0
|
39
|
+
version: 1.0.0
|
40
40
|
email:
|
41
41
|
- azimux@gmail.com
|
42
42
|
executables: []
|