helicone-rb 0.1.3 → 0.2.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: 210ac6dc40e739a7ee0ff0478dfec18c300f786afd0b4f149a57048b1bd46ce9
4
- data.tar.gz: a11ef6687f94ebdf9c9adcc56635256388718be341941fe13258ec8930c8fe29
3
+ metadata.gz: ac034e0153e6ec01bbe008066b48c58c754a103b56461fdc24c4e0d1bc05d4d4
4
+ data.tar.gz: c95390c56a649b16fde96f7be81a1ef537671a19a129039d23d272ea391cfdaf
5
5
  SHA512:
6
- metadata.gz: a9b4f50614b0f88b150f5a6457f0fb0c8fef5046451a59a5963225202af5f72b6f72602df6b54c10996cd271ce192c1c5e6902198e744b2dafe06021964ab913
7
- data.tar.gz: f887ebe7105b9287cdfaa94df8af657c69af7d28e8bc5760c5dc1aabfd5c9ddad7a3297efe9b713542e58fcfd640780079ffddc044e78fb6b203e38eb3111b31
6
+ metadata.gz: a4726d935f0db71a01ece1db9f29d758f2c4f47e04b79cb62ed986f1180abf6415576ccfa94e1de6e6d73671d21448c8067b1c74b6b55052195548c67533f64b
7
+ data.tar.gz: 1b1b93d6cffe0e19a41dbbefec03ab019bda992c4eb7a0dfc7770c60852f7dfde8d879d634aeeec10ca75837e799919be2ecc14f9f601efbb4b63636922b43ec
@@ -4,7 +4,7 @@ module Helicone
4
4
  class Agent
5
5
  MAX_ITERATIONS = 10
6
6
 
7
- attr_reader :client, :tools, :messages, :context
7
+ attr_reader :client, :tools, :messages, :context, :turn_model, :response_model
8
8
 
9
9
  # Create an agent with tools and optional context
10
10
  #
@@ -14,10 +14,14 @@ module Helicone
14
14
  # @param context [Object] Context object passed to tool#initialize
15
15
  # @param system_prompt [String] System prompt
16
16
  # @param messages [Array<Helicone::Message>] Initial messages (for continuing conversations)
17
- def initialize(client: nil, session: nil, tools: [], context: nil, system_prompt: nil, messages: [])
17
+ # @param turn_model [String] Model for tool-calling turns (defaults to Helicone.configuration.default_model)
18
+ # @param response_model [String] Model for final response (defaults to turn_model)
19
+ def initialize(client: nil, session: nil, tools: [], context: nil, system_prompt: nil, messages: [], turn_model: nil, response_model: nil)
18
20
  @client = client || build_client(session: session)
19
21
  @tools = tools
20
22
  @context = context
23
+ @turn_model = turn_model
24
+ @response_model = response_model || turn_model
21
25
  @messages = messages.dup
22
26
 
23
27
  # Add system message at the start if provided and not already present
@@ -26,17 +30,17 @@ module Helicone
26
30
  end
27
31
  end
28
32
 
29
- # Run the agent with a prompt, executing tools until done
33
+ # Run the agent with an optional prompt, executing tools until done
30
34
  #
31
- # @param prompt [String] User prompt to start with
35
+ # @param prompt [String, nil] User prompt to add (nil to use existing messages)
32
36
  # @param max_iterations [Integer] Maximum tool execution loops
33
37
  # @return [AgentResult]
34
- def run(prompt, max_iterations: MAX_ITERATIONS)
35
- @messages << Message.user_text(prompt)
38
+ def run(prompt = nil, max_iterations: MAX_ITERATIONS)
39
+ @messages << Message.user_text(prompt) if prompt
36
40
 
37
41
  iterations = 0
38
42
  while iterations < max_iterations
39
- response = call_llm
43
+ response = call_llm(model: @turn_model)
40
44
 
41
45
  tool_calls = response.tool_calls
42
46
  if tool_calls && !tool_calls.empty?
@@ -55,7 +59,17 @@ module Helicone
55
59
 
56
60
  iterations += 1
57
61
  else
58
- # No tool calls - we're done
62
+ # No tool calls - if response_model differs, make final call with it
63
+ if @response_model && @response_model != @turn_model
64
+ final_response = @client.chat(messages: @messages, model: @response_model)
65
+ return AgentResult.new(
66
+ content: final_response.content,
67
+ messages: @messages,
68
+ iterations: iterations,
69
+ response: final_response
70
+ )
71
+ end
72
+
59
73
  return AgentResult.new(
60
74
  content: response.content,
61
75
  messages: @messages,
@@ -66,7 +80,7 @@ module Helicone
66
80
  end
67
81
 
68
82
  # Max iterations reached - make one final call without tools to get a response
69
- final_response = @client.chat(messages: @messages)
83
+ final_response = @client.chat(messages: @messages, model: @response_model)
70
84
 
71
85
  AgentResult.new(
72
86
  content: final_response.content,
@@ -92,9 +106,10 @@ module Helicone
92
106
  Helicone.configuration.logger
93
107
  end
94
108
 
95
- def call_llm
109
+ def call_llm(model: nil)
96
110
  @client.chat(
97
111
  messages: @messages,
112
+ model: model,
98
113
  tools: tools_for_api,
99
114
  tool_choice: "auto"
100
115
  )
@@ -106,16 +121,17 @@ module Helicone
106
121
  end
107
122
 
108
123
  def execute_tool(tool_call)
109
- tool_class = find_tool_class(tool_call.name)
124
+ tool = find_tool(tool_call.name)
110
125
 
111
- unless tool_class
126
+ unless tool
112
127
  logger.warn("[Helicone::Agent] Unknown tool: #{tool_call.name}")
113
128
  return { error: "Unknown tool: #{tool_call.name}" }
114
129
  end
115
130
 
116
131
  logger.info("[Helicone::Agent] Executing tool: #{tool_call.name} with #{tool_call.arguments}")
117
132
 
118
- tool_instance = tool_class.new(@context)
133
+ # Support both tool classes and tool instances
134
+ tool_instance = tool.is_a?(Class) ? tool.new(@context) : tool
119
135
  result = tool_instance.execute(**tool_call.arguments)
120
136
 
121
137
  result_preview = result.inspect
@@ -128,7 +144,7 @@ module Helicone
128
144
  { error: e.message }
129
145
  end
130
146
 
131
- def find_tool_class(name)
147
+ def find_tool(name)
132
148
  @tools.find { |t| t.function_name == name }
133
149
  end
134
150
 
@@ -13,7 +13,7 @@ module Helicone
13
13
  def initialize(session_id: nil, session_name: nil, account_id: nil, account_name: nil)
14
14
  @client = OpenAI::Client.new(
15
15
  access_token: ENV["HELICONE_API_KEY"],
16
- uri_base: Helicone::URI_BASE
16
+ uri_base: Helicone.configuration.base_url
17
17
  )
18
18
 
19
19
  # Add Helicone session headers if provided
@@ -3,16 +3,17 @@
3
3
  require "logger"
4
4
 
5
5
  module Helicone
6
- URI_BASE = "https://ai-gateway.helicone.ai/v1"
6
+ DEFAULT_BASE_URL = "https://ai-gateway.helicone.ai/v1"
7
7
 
8
8
  class Configuration
9
- attr_accessor :logger, :default_model
9
+ attr_accessor :logger, :default_model, :base_url
10
10
 
11
11
  # Initialize configuration with defaults
12
12
  #
13
13
  # @return [Configuration]
14
14
  def initialize
15
15
  @default_model = "gpt-4o"
16
+ @base_url = DEFAULT_BASE_URL
16
17
  @logger = Logger.new($stdout, level: Logger::INFO)
17
18
  end
18
19
  end
@@ -113,9 +113,11 @@ module Helicone
113
113
  #
114
114
  # @return [Hash] Message formatted for the API
115
115
  def to_h
116
- # If this is a raw message (assistant with tool_calls), return it as-is
117
116
  if @raw_message
118
- @raw_message
117
+ # Select only the fields needed for the API
118
+ hash = { role: @raw_message[:role], content: @raw_message[:content] }
119
+ hash[:tool_calls] = @raw_message[:tool_calls] if @raw_message[:tool_calls]
120
+ hash
119
121
  else
120
122
  hash = { role: role, content: content }
121
123
  hash[:tool_call_id] = tool_call_id if tool_call_id
data/lib/helicone/tool.rb CHANGED
@@ -98,5 +98,19 @@ module Helicone
98
98
  def execute(**args)
99
99
  raise NotImplementedError, "Subclasses must implement #execute"
100
100
  end
101
+
102
+ # Delegate to class method for instances
103
+ #
104
+ # @return [Hash] Tool definition formatted for OpenAI API
105
+ def to_openai_tool
106
+ self.class.to_openai_tool
107
+ end
108
+
109
+ # Delegate to class method for instances
110
+ #
111
+ # @return [String] The function name
112
+ def function_name
113
+ self.class.function_name
114
+ end
101
115
  end
102
116
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Helicone
4
- VERSION = "0.1.3"
4
+ VERSION = "0.2.1"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: helicone-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Genevere