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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dc4b3804b5930b121fdc679ecf203b9e8b4d11122d24da967cfbfd10a1e6562d
4
- data.tar.gz: '0739391b9b59d453783756a8efed38ec3d559ce7636873776ee71a14027059b5'
3
+ metadata.gz: dc32aeaa66ec947920e085944f7948d22d97b4fa3b39d1a4b4fbf58755ca4321
4
+ data.tar.gz: 0dc7b3d02061bf0a615ab6299ea5f607fff1d703804d5368b57a9157d4edf64a
5
5
  SHA512:
6
- metadata.gz: 0ff04dba39a3edae5a80a98234cd7708c2f90d30bded9f12a0e2b665ea640c302e1ed14c607d61533daa5a0b3d7712684d92de740a3f3e085a1704286f95b837
7
- data.tar.gz: 252b0f1a1c298bd984a856f4e63e57808b63cace046d58cf82f8c55f391c6d21fb3d98b8dda869582aa995eb6438a2fe998bae3952c5f6791eca00d25c5d181c
6
+ metadata.gz: e1a1d3780d7a3112cff93e7e626ec677ad558ce605e65c60f00ec3b8213b604e248ca4428311303b1902451f2bcc7d2a5f17f3725dde77bbb4725aeb10b9898d
7
+ data.tar.gz: f6113517024dc34e999fafcb3bc5ee0ec98fb63628f61725b5631e454d6edd4714933a745232e57f2a1c8f686f0d2544b481b1726cfff3e4dbbc47666bdd74c4
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## [0.0.14] - 2025-07-08
2
+
3
+ - Better handle serialization/pre-commit loading for various entity-depth scenarios
4
+
1
5
  ## [0.0.13] - 2025-07-06
2
6
 
3
7
  - Eliminate NotifyUser... result_type to save tokens/improve accuracy
@@ -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
- result_entity_depth :symbol, :allow_nil, one_of: [:atom, :aggregate]
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
- simulate_describe_list_commands_command
45
- simulate_list_commands_run
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 = { context:, llm_model: }
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
- context Context, :required, "Context of the progress towards the goal so far"
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
- Foobara::JsonSchemaGenerator::AssociationDepth::ATOM
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
- # unless opts.key?(:default_serializers)
56
- # opts = opts.merge(default_serializers: [
57
- # Foobara::CommandConnectors::Serializers::ErrorsSerializer,
58
- # Foobara::CommandConnectors::Serializers::AggregateSerializer
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
- unless opts.key?(:default_pre_commit_transformers)
63
- opts = opts.merge(
64
- default_pre_commit_transformers: Foobara::CommandConnectors::Transformers::LoadAtomsPreCommitTransformer
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.13
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.1
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.1
39
+ version: 1.0.0
40
40
  email:
41
41
  - azimux@gmail.com
42
42
  executables: []