helicone-rb 0.2.0 → 0.3.0
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 +18 -29
- 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: a118f742137f788207fb3e4b724ec2420884ef5610776d1437385cd2fa963649
|
|
4
|
+
data.tar.gz: 44b4d16c5295b974afa28d2b9f694bf0c2b0cb95ba810826eaa5a72b141cd1e1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b689d259dbc4f8b583a62d5b95e84053aa58f41d594cf03fb5b681dc10d180e4d3ab5d86844d9875821c3d6b8c3270ff7e5faf5660c89501a8e72e8e7bf9d1b0
|
|
7
|
+
data.tar.gz: 6aa3ef6dda08bccd058deb550c23a0059693f759476b8394fa0d0c5f24497475decd2beb81a7f5818c6a58e243b8d8484bda22e405fcd965ae602bd789451904
|
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, :model
|
|
8
8
|
|
|
9
9
|
# Create an agent with tools and optional context
|
|
10
10
|
#
|
|
@@ -14,14 +14,12 @@ 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
|
-
# @param
|
|
18
|
-
|
|
19
|
-
def initialize(client: nil, session: nil, tools: [], context: nil, system_prompt: nil, messages: [], turn_model: nil, response_model: nil)
|
|
17
|
+
# @param model [String] Model to use (defaults to Helicone.configuration.default_model)
|
|
18
|
+
def initialize(client: nil, session: nil, tools: [], context: nil, system_prompt: nil, messages: [], model: nil)
|
|
20
19
|
@client = client || build_client(session: session)
|
|
21
20
|
@tools = tools
|
|
22
21
|
@context = context
|
|
23
|
-
@
|
|
24
|
-
@response_model = response_model || turn_model
|
|
22
|
+
@model = model
|
|
25
23
|
@messages = messages.dup
|
|
26
24
|
|
|
27
25
|
# Add system message at the start if provided and not already present
|
|
@@ -30,17 +28,17 @@ module Helicone
|
|
|
30
28
|
end
|
|
31
29
|
end
|
|
32
30
|
|
|
33
|
-
# Run the agent with
|
|
31
|
+
# Run the agent with an optional prompt, executing tools until done
|
|
34
32
|
#
|
|
35
|
-
# @param prompt [String] User prompt to
|
|
33
|
+
# @param prompt [String, nil] User prompt to add (nil to use existing messages)
|
|
36
34
|
# @param max_iterations [Integer] Maximum tool execution loops
|
|
37
35
|
# @return [AgentResult]
|
|
38
|
-
def run(prompt, max_iterations: MAX_ITERATIONS)
|
|
39
|
-
@messages << Message.user_text(prompt)
|
|
36
|
+
def run(prompt = nil, max_iterations: MAX_ITERATIONS)
|
|
37
|
+
@messages << Message.user_text(prompt) if prompt
|
|
40
38
|
|
|
41
39
|
iterations = 0
|
|
42
40
|
while iterations < max_iterations
|
|
43
|
-
response = call_llm
|
|
41
|
+
response = call_llm
|
|
44
42
|
|
|
45
43
|
tool_calls = response.tool_calls
|
|
46
44
|
if tool_calls && !tool_calls.empty?
|
|
@@ -59,17 +57,7 @@ module Helicone
|
|
|
59
57
|
|
|
60
58
|
iterations += 1
|
|
61
59
|
else
|
|
62
|
-
# No tool calls -
|
|
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
|
-
|
|
60
|
+
# No tool calls - we're done
|
|
73
61
|
return AgentResult.new(
|
|
74
62
|
content: response.content,
|
|
75
63
|
messages: @messages,
|
|
@@ -80,7 +68,7 @@ module Helicone
|
|
|
80
68
|
end
|
|
81
69
|
|
|
82
70
|
# Max iterations reached - make one final call without tools to get a response
|
|
83
|
-
final_response = @client.chat(messages: @messages, model: @
|
|
71
|
+
final_response = @client.chat(messages: @messages, model: @model)
|
|
84
72
|
|
|
85
73
|
AgentResult.new(
|
|
86
74
|
content: final_response.content,
|
|
@@ -106,10 +94,10 @@ module Helicone
|
|
|
106
94
|
Helicone.configuration.logger
|
|
107
95
|
end
|
|
108
96
|
|
|
109
|
-
def call_llm
|
|
97
|
+
def call_llm
|
|
110
98
|
@client.chat(
|
|
111
99
|
messages: @messages,
|
|
112
|
-
model: model,
|
|
100
|
+
model: @model,
|
|
113
101
|
tools: tools_for_api,
|
|
114
102
|
tool_choice: "auto"
|
|
115
103
|
)
|
|
@@ -121,16 +109,17 @@ module Helicone
|
|
|
121
109
|
end
|
|
122
110
|
|
|
123
111
|
def execute_tool(tool_call)
|
|
124
|
-
|
|
112
|
+
tool = find_tool(tool_call.name)
|
|
125
113
|
|
|
126
|
-
unless
|
|
114
|
+
unless tool
|
|
127
115
|
logger.warn("[Helicone::Agent] Unknown tool: #{tool_call.name}")
|
|
128
116
|
return { error: "Unknown tool: #{tool_call.name}" }
|
|
129
117
|
end
|
|
130
118
|
|
|
131
119
|
logger.info("[Helicone::Agent] Executing tool: #{tool_call.name} with #{tool_call.arguments}")
|
|
132
120
|
|
|
133
|
-
|
|
121
|
+
# Support both tool classes and tool instances
|
|
122
|
+
tool_instance = tool.is_a?(Class) ? tool.new(@context) : tool
|
|
134
123
|
result = tool_instance.execute(**tool_call.arguments)
|
|
135
124
|
|
|
136
125
|
result_preview = result.inspect
|
|
@@ -143,7 +132,7 @@ module Helicone
|
|
|
143
132
|
{ error: e.message }
|
|
144
133
|
end
|
|
145
134
|
|
|
146
|
-
def
|
|
135
|
+
def find_tool(name)
|
|
147
136
|
@tools.find { |t| t.function_name == name }
|
|
148
137
|
end
|
|
149
138
|
|
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