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 +4 -4
- data/lib/helicone/agent.rb +30 -14
- data/lib/helicone/client.rb +1 -1
- data/lib/helicone/configuration.rb +3 -2
- data/lib/helicone/message.rb +4 -2
- data/lib/helicone/tool.rb +14 -0
- data/lib/helicone/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ac034e0153e6ec01bbe008066b48c58c754a103b56461fdc24c4e0d1bc05d4d4
|
|
4
|
+
data.tar.gz: c95390c56a649b16fde96f7be81a1ef537671a19a129039d23d272ea391cfdaf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a4726d935f0db71a01ece1db9f29d758f2c4f47e04b79cb62ed986f1180abf6415576ccfa94e1de6e6d73671d21448c8067b1c74b6b55052195548c67533f64b
|
|
7
|
+
data.tar.gz: 1b1b93d6cffe0e19a41dbbefec03ab019bda992c4eb7a0dfc7770c60852f7dfde8d879d634aeeec10ca75837e799919be2ecc14f9f601efbb4b63636922b43ec
|
data/lib/helicone/agent.rb
CHANGED
|
@@ -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
|
-
|
|
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
|
|
33
|
+
# Run the agent with an optional prompt, executing tools until done
|
|
30
34
|
#
|
|
31
|
-
# @param prompt [String] User prompt to
|
|
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 -
|
|
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
|
-
|
|
124
|
+
tool = find_tool(tool_call.name)
|
|
110
125
|
|
|
111
|
-
unless
|
|
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
|
-
|
|
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
|
|
147
|
+
def find_tool(name)
|
|
132
148
|
@tools.find { |t| t.function_name == name }
|
|
133
149
|
end
|
|
134
150
|
|
data/lib/helicone/client.rb
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
data/lib/helicone/message.rb
CHANGED
|
@@ -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
|
-
|
|
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
|
data/lib/helicone/version.rb
CHANGED