ruby-openai-swarm 0.2.9 → 0.3.0.1

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: df40e898023940bd9fa16596e947caf353dc8ce3edeee3d442cb871a8e5bbba0
4
- data.tar.gz: c180214e63813c09bea2c986a3c7c1729f458f66a807a2b578d4f71b8b39374b
3
+ metadata.gz: 98aa27742c5ae980d9c1c8b9457beb2e61a4ff3a1548790d4205cd0f68cef039
4
+ data.tar.gz: 37d7a5280f47c2a454a2aba4a5f64587787f1e829fc07b6c27accc90f63f91f8
5
5
  SHA512:
6
- metadata.gz: 6e16aa9fa53293212ccdb96dba442da4e48db77dd217b749b9bfd80a4711324ac3adaf6bc11b28e27ea348d0a055921d7e1f98fa70dbecb0c4d17bcd7514473b
7
- data.tar.gz: 8450574be9da37c9c5fcd67e25ba564795f5b475fe78df337a69561ca2f8b5f09ea100b01d3547b1a6dcb510c56614db6f2a3148693588d6b6e432386cd6231c
6
+ metadata.gz: 0d671ef9fa72e895bfd3b3e62561fccfc3894a6f19605dd43e68da14b0c9f958d22559da8d9eecd981277a7db035ed39c17535f261cf40849f16a95ac6884516
7
+ data.tar.gz: 96c6229510613dbb8b858200916bb9ab22583b7918d604adae0b1bc85bb5b89cfae28a6c833b8c16b2acc1758d1d89643c61f240c896ff6d1d3153536801b46d
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ruby-openai-swarm (0.2.9)
4
+ ruby-openai-swarm (0.3.0.1)
5
5
  ruby-openai (~> 7.3)
6
6
 
7
7
  GEM
@@ -65,4 +65,4 @@ params:
65
65
  GUIDE_EXAMPLES
66
66
  puts guide_examples
67
67
 
68
- OpenAISwarm::Repl.run_demo_loop(triage_agent, context_variables: context_variables, debug: env_debug)
68
+ OpenAISwarm::Repl.run_demo_loop(triage_agent, context_variables: context_variables, stream: true, debug: env_debug)
@@ -46,6 +46,7 @@ Details:
46
46
  Example: “What’s the weather in NYC?”
47
47
  Action: Calls get_weather with location “New York City”.
48
48
  Response: Only provides weather details.
49
+
49
50
  2. Multiple Function Calls
50
51
  Example: “Tell me the weather in New York and the latest news headlines.”
51
52
  Action: Calls get_weather for weather and get_news for news.
@@ -58,4 +59,19 @@ GUIDE_EXAMPLES
58
59
 
59
60
  puts guide_examples
60
61
 
61
- OpenAISwarm::Repl.run_demo_loop(agent, stream: true, debug: env_debug)
62
+ # OpenAISwarm::Repl.run_demo_loop(agent, stream: true, debug: env_debug)
63
+
64
+ OpenAISwarm.new.run_and_stream(
65
+ agent: agent,
66
+ debug: true,
67
+ messages: [{"role" => "user", "content" => "Tell me the weather in New York and the latest news headlines."}]
68
+ ) do |chunk|
69
+ if chunk.key?("content") && !chunk["content"].nil?
70
+ puts ">>>#{chunk}"
71
+ end
72
+
73
+ if chunk.key?('response')
74
+ binding.pry
75
+ # log_llm_request(chunk['response'])
76
+ end
77
+ end
@@ -3,7 +3,9 @@ module OpenAISwarm
3
3
  attr_accessor :name, :model, :instructions,
4
4
  :functions, :tool_choice,
5
5
  :parallel_tool_calls,
6
+ :strategy,
6
7
  :noisy_tool_calls,
8
+ :temperature,
7
9
  :resource
8
10
  # These attributes can be read and written externally. They include:
9
11
  # - name: The name of the agent.
@@ -19,18 +21,22 @@ module OpenAISwarm
19
21
  instructions: "You are a helpful agent.",
20
22
  functions: [],
21
23
  tool_choice: nil,
24
+ temperature: nil,
22
25
  parallel_tool_calls: true,
23
26
  resource: nil,
24
- noisy_tool_calls: []
27
+ noisy_tool_calls: [],
28
+ strategy: {}
25
29
  )
26
30
  @name = name
27
31
  @model = model
28
32
  @instructions = instructions
29
33
  @functions = functions
30
34
  @tool_choice = tool_choice
35
+ @temperature = temperature
31
36
  @parallel_tool_calls = parallel_tool_calls
32
37
  @resource = resource
33
38
  @noisy_tool_calls = noisy_tool_calls
39
+ @strategy = Agents::StrategyOptions.new(strategy)
34
40
  end
35
41
  end
36
42
  end
@@ -0,0 +1,24 @@
1
+ module OpenAISwarm
2
+ module Agents
3
+ class ChangeTracker
4
+ attr_reader :current_agent, :previous_agent
5
+
6
+ def initialize(agent)
7
+ update(agent)
8
+ end
9
+
10
+ def update(agent)
11
+ @previous_agent = @current_agent
12
+ @current_agent = agent
13
+ end
14
+
15
+ def agent_changed?
16
+ previous_agent&.name != current_agent&.name
17
+ end
18
+
19
+ def switch_agent_reset_message?
20
+ agent_changed? && current_agent.strategy.switch_agent_reset_message
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,11 @@
1
+ module OpenAISwarm
2
+ module Agents
3
+ class StrategyOptions
4
+ attr_accessor :switch_agent_reset_message
5
+
6
+ def initialize(strategy = {})
7
+ @switch_agent_reset_message = strategy[:switch_agent_reset_message] || false
8
+ end
9
+ end
10
+ end
11
+ end
@@ -14,7 +14,8 @@ module OpenAISwarm
14
14
  @logger = OpenAISwarm::Logger.instance.logger
15
15
  end
16
16
 
17
- def get_chat_completion(agent, history, context_variables, model_override, stream, debug)
17
+ def get_chat_completion(agent_tracker, history, context_variables, model_override, stream, debug)
18
+ agent = agent_tracker.current_agent
18
19
  context_variables = context_variables.dup
19
20
  instructions = agent.instructions.respond_to?(:call) ? agent.instructions.call(context_variables) : agent.instructions
20
21
  messages = [{ role: 'system', content: instructions }] + history
@@ -41,6 +42,7 @@ module OpenAISwarm
41
42
  # create_params[:functions] = tools unless tools.empty?
42
43
  # create_params[:function_call] = agent.tool_choice if agent.tool_choice
43
44
 
45
+ create_params[:temperature] = agent.temperature if agent.temperature
44
46
  create_params[:tool_choice] = agent.tool_choice if agent.tool_choice
45
47
  create_params[:parallel_tool_calls] = agent.parallel_tool_calls if tools.any?
46
48
 
@@ -146,6 +148,7 @@ module OpenAISwarm
146
148
  end
147
149
 
148
150
  def run(agent:, messages:, context_variables: {}, model_override: nil, stream: false, debug: false, max_turns: Float::INFINITY, execute_tools: true)
151
+ agent_tracker = OpenAISwarm::Agents::ChangeTracker.new(agent)
149
152
  if stream
150
153
  return run_and_stream(
151
154
  agent: agent,
@@ -164,8 +167,11 @@ module OpenAISwarm
164
167
  init_len = messages.length
165
168
 
166
169
  while history.length - init_len < max_turns && active_agent
170
+ agent_tracker.update(active_agent)
171
+ history = OpenAISwarm::Util.latest_role_user_message(history) if agent_tracker.switch_agent_reset_message?
172
+
167
173
  completion = get_chat_completion(
168
- active_agent,
174
+ agent_tracker,
169
175
  history,
170
176
  context_variables,
171
177
  model_override,
@@ -204,16 +210,21 @@ module OpenAISwarm
204
210
  )
205
211
  end
206
212
 
213
+ # TODO(Grayson): a lot of copied code here that will be refactored
207
214
  def run_and_stream(agent:, messages:, context_variables: {}, model_override: nil, debug: false, max_turns: Float::INFINITY, execute_tools: true)
215
+ agent_tracker = OpenAISwarm::Agents::ChangeTracker.new(agent)
208
216
  active_agent = agent
209
217
  context_variables = context_variables.dup
210
218
  history = messages.dup
211
219
  init_len = messages.length
212
220
 
213
221
  while history.length - init_len < max_turns && active_agent
222
+ agent_tracker.update(active_agent)
223
+ history = OpenAISwarm::Util.latest_role_user_message(history) if agent_tracker.switch_agent_reset_message?
224
+
214
225
  message = OpenAISwarm::Util.message_template(agent.name)
215
226
  completion = get_chat_completion(
216
- active_agent,
227
+ agent_tracker,
217
228
  history,
218
229
  context_variables,
219
230
  model_override,
@@ -1,5 +1,13 @@
1
1
  module OpenAISwarm
2
2
  module Util
3
+ class << self
4
+ def latest_role_user_message(history)
5
+ return history if history.empty?
6
+ filtered_messages = symbolize_keys_to_string(history.dup)
7
+ last_user_message = filtered_messages.reverse.find { |msg| msg['role'] == 'user' }
8
+ last_user_message ? [last_user_message] : history
9
+ end
10
+ end
3
11
  def self.debug_print(debug, *args)
4
12
  return unless debug
5
13
  timestamp = Time.now.strftime("%Y-%m-%d %H:%M:%S")
@@ -1,3 +1,3 @@
1
1
  module OpenAISwarm
2
- VERSION = "0.2.9"
2
+ VERSION = "0.3.0.1"
3
3
  end
@@ -1,6 +1,8 @@
1
1
  require 'ruby-openai-swarm/version'
2
2
  require 'ruby-openai-swarm/core_ext'
3
3
  require 'ruby-openai-swarm/agent'
4
+ require 'ruby-openai-swarm/agents/change_tracker'
5
+ require 'ruby-openai-swarm/agents/strategy_options'
4
6
  require 'ruby-openai-swarm/response'
5
7
  require 'ruby-openai-swarm/result'
6
8
  require 'ruby-openai-swarm/util'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-openai-swarm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.9
4
+ version: 0.3.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Grayson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-12-14 00:00:00.000000000 Z
11
+ date: 2024-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ruby-openai
@@ -106,6 +106,8 @@ files:
106
106
  - examples/weather_agent/run.rb
107
107
  - lib/ruby-openai-swarm.rb
108
108
  - lib/ruby-openai-swarm/agent.rb
109
+ - lib/ruby-openai-swarm/agents/change_tracker.rb
110
+ - lib/ruby-openai-swarm/agents/strategy_options.rb
109
111
  - lib/ruby-openai-swarm/configuration.rb
110
112
  - lib/ruby-openai-swarm/core.rb
111
113
  - lib/ruby-openai-swarm/core_ext.rb