Skip to content

Commit 5b5b17c

Browse files
committed
[WIP] Create Improved Messages Common Format - OpenAI
1 parent 197ea3f commit 5b5b17c

File tree

111 files changed

+71760
-649
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

111 files changed

+71760
-649
lines changed

lib/active_agent/providers/_base_provider.rb

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def initialize(kwargs = {})
7979
# @raise [StandardError] provider-specific errors wrapped by error handling
8080
def prompt
8181
instrument("prompt_start.provider.active_agent") do
82-
self.request = prompt_request_klass.new(context.except(:trace_id))
82+
self.request = prompt_request_type.cast(context.except(:trace_id))
8383
resolve_prompt
8484
end
8585
end
@@ -92,7 +92,7 @@ def prompt
9292
# @raise [StandardError] provider-specific errors wrapped by error handling
9393
def embed
9494
instrument("embed_start.provider.active_agent") do
95-
self.request = embed_request_klass.new(context.except(:trace_id))
95+
self.request = embed_request_type.cast(context.except(:trace_id))
9696
resolve_embed
9797
end
9898
end
@@ -115,12 +115,12 @@ def namespace
115115
# @return [Class]
116116
def options_klass = namespace::Options
117117

118-
# @return [Class]
119-
def prompt_request_klass = namespace::Request
118+
# @return [ActiveModel::Type::Value] provider-specific RequestType for casting/serialization
119+
def prompt_request_type = namespace::RequestType.new
120120

121-
# @return [Class] provider-specific EmbedRequest class
121+
# @return [ActiveModel::Type::Value] provider-specific RequestType for embedding casting/serialization
122122
# @raise [NotImplementedError] when provider doesn't support embeddings
123-
def embed_request_klass = fail(NotImplementedError)
123+
def embed_request_type = fail(NotImplementedError)
124124

125125
protected
126126

@@ -155,7 +155,7 @@ def resolve_prompt
155155
instrument("request_prepared.provider.active_agent", message_count: request.messages.size)
156156

157157
# @todo Validate Request
158-
api_parameters = api_request_build(request)
158+
api_parameters = api_request_build(request, prompt_request_type)
159159
api_response = instrument("api_call.provider.active_agent", streaming: api_parameters[:stream].present?) do
160160
retriable { api_prompt_execute(api_parameters) }
161161
end
@@ -168,7 +168,7 @@ def resolve_prompt
168168
# @return [ActiveAgent::Providers::Common::EmbedResponse]
169169
def resolve_embed
170170
# @todo Validate Request
171-
api_parameters = api_request_build(self.request)
171+
api_parameters = api_request_build(request, embed_request_type)
172172
api_response = instrument("embed_call.provider.active_agent") do
173173
retriable { api_embed_execute(api_parameters) }
174174
end
@@ -191,9 +191,10 @@ def prepare_prompt_request
191191
# Builds API request parameters from request object.
192192
#
193193
# @param request [Request]
194+
# @param request_type [ActiveModel::Type::Value] The type to use for serialization
194195
# @return [Hash]
195-
def api_request_build(request)
196-
parameters = request.serialize
196+
def api_request_build(request, request_type)
197+
parameters = request_type.serialize(request)
197198
parameters[:stream] = process_stream if request.try(:stream)
198199
parameters
199200
end
@@ -292,14 +293,14 @@ def process_prompt_finished(api_response = nil)
292293

293294
# To convert the messages into common format we first need to merge the current
294295
# stack and then cast them to the provider type, so we can cast them out to common.
295-
messages = prompt_request_klass.new(
296+
messages = prompt_request_type.cast(
296297
messages: [ *request.messages, *message_stack ]
297298
).messages
298299

299300
# This will returned as it closes up the recursive stack
300301
Common::PromptResponse.new(
301302
context:,
302-
raw_request: request.serialize,
303+
raw_request: prompt_request_type.serialize(request),
303304
raw_response: api_response,
304305
messages:
305306
)
@@ -332,7 +333,7 @@ def process_prompt_finished_extract_function_calls
332333
def process_embed_finished(api_response)
333334
Common::EmbedResponse.new(
334335
context:,
335-
raw_request: request.serialize,
336+
raw_request: embed_request_type.serialize(request),
336337
raw_response: api_response,
337338
data: process_embed_finished_data(api_response)
338339
)
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,45 @@
1+
# frozen_string_literal: true
2+
13
require_relative "requests/_types"
24

35
require_relative "options"
46
require_relative "request"
7+
8+
module ActiveAgent
9+
module Providers
10+
module Anthropic
11+
# Type for Request model
12+
class RequestType < ActiveModel::Type::Value
13+
def cast(value)
14+
case value
15+
when Request
16+
value
17+
when Hash
18+
Request.new(**value.deep_symbolize_keys)
19+
when nil
20+
nil
21+
else
22+
raise ArgumentError, "Cannot cast #{value.class} to Request"
23+
end
24+
end
25+
26+
def serialize(value)
27+
case value
28+
when Request
29+
value.serialize
30+
when Hash
31+
value
32+
when nil
33+
nil
34+
else
35+
raise ArgumentError, "Cannot serialize #{value.class}"
36+
end
37+
end
38+
39+
def deserialize(value)
40+
cast(value)
41+
end
42+
end
43+
end
44+
end
45+
end

lib/active_agent/providers/anthropic/requests/_types.rb

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ def cast(value)
2020
when ContainerParams
2121
value
2222
when Hash
23-
# Symbolize keys once for consistent lookups
24-
ContainerParams.new(**value.symbolize_keys)
23+
ContainerParams.new(**value.deep_symbolize_keys)
2524
when String
2625
# Allow string as container ID shortcut
2726
ContainerParams.new(id: value)
@@ -57,8 +56,7 @@ def cast(value)
5756
when ContextManagementConfig
5857
value
5958
when Hash
60-
# Symbolize keys once for consistent lookups
61-
ContextManagementConfig.new(**value.symbolize_keys)
59+
ContextManagementConfig.new(**value.deep_symbolize_keys)
6260
when nil
6361
nil
6462
else
@@ -91,8 +89,7 @@ def cast(value)
9189
when Metadata
9290
value
9391
when Hash
94-
# Symbolize keys once for consistent lookups
95-
Metadata.new(**value.symbolize_keys)
92+
Metadata.new(**value.deep_symbolize_keys)
9693
when nil
9794
nil
9895
else

lib/active_agent/providers/anthropic/requests/messages/_types.rb

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,13 @@ def cast(value)
6464
when String
6565
User.new(content: value)
6666
when Hash
67-
# Symbolize keys once for consistent lookups
68-
hash = value.symbolize_keys
69-
role = hash[:role]&.to_s
67+
hash = value.deep_symbolize_keys
68+
role = hash[:role]&.to_sym
7069

7170
case role
72-
when "user", nil
71+
when :user, nil
7372
User.new(**hash)
74-
when "assistant"
73+
when :assistant
7574
Assistant.new(**hash)
7675
else
7776
raise ArgumentError, "Unknown message role: #{role}"
@@ -158,12 +157,11 @@ def cast_system_block(value)
158157
when String
159158
Content::Text.new(text: value)
160159
when Hash
161-
# Symbolize keys once for consistent lookups
162-
hash = value.symbolize_keys
163-
type = hash[:type]&.to_s
160+
hash = value.deep_symbolize_keys
161+
type = hash[:type]&.to_sym
164162

165163
case type
166-
when "text"
164+
when :text
167165
Content::Text.new(**hash)
168166
else
169167
raise ArgumentError, "Unknown system block type: #{type}"

lib/active_agent/providers/anthropic/requests/messages/content/_types.rb

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -71,26 +71,25 @@ def cast(value)
7171
# Already a Content object, return as-is
7272
value
7373
when Hash
74-
# Symbolize keys once for consistent lookups
75-
hash = value.symbolize_keys
76-
type = hash[:type]&.to_s
74+
hash = value.deep_symbolize_keys
75+
type = hash[:type]&.to_sym
7776

7877
case type
79-
when "text"
78+
when :text
8079
Text.new(**hash)
81-
when "image"
80+
when :image
8281
Image.new(**hash)
83-
when "document"
82+
when :document
8483
Document.new(**hash)
85-
when "tool_use"
84+
when :tool_use
8685
ToolUse.new(**hash)
87-
when "tool_result"
86+
when :tool_result
8887
ToolResult.new(**hash)
89-
when "thinking"
88+
when :thinking
9089
Thinking.new(**hash)
91-
when "redacted_thinking"
90+
when :redacted_thinking
9291
RedactedThinking.new(**hash)
93-
when "search_result"
92+
when :search_result
9493
SearchResult.new(**hash)
9594
when nil
9695
# No type specified - infer from keys present
@@ -129,7 +128,7 @@ def serialize(value)
129128
when nil
130129
nil
131130
else
132-
value
131+
raise ArgumentError, "Cannot serialize #{value.class} as Content"
133132
end
134133
end
135134

lib/active_agent/providers/anthropic/requests/messages/content/sources/_types.rb

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,27 +23,26 @@ def cast(value)
2323
# Already a Source object, return as-is
2424
value
2525
when Hash
26-
# Symbolize keys once for consistent lookups
27-
hash = value.symbolize_keys
28-
type = hash[:type]&.to_s
26+
hash = value.deep_symbolize_keys
27+
type = hash[:type]&.to_sym
2928

3029
case type
31-
when "base64"
30+
when :base64
3231
# Determine if it's image or document based on media_type or context
3332
media_type = hash[:media_type]&.to_s
3433
if media_type&.start_with?("image/")
3534
ImageBase64.new(**hash)
3635
else
3736
DocumentBase64.new(**hash)
3837
end
39-
when "url"
38+
when :url
4039
# Could be either - default to image for now
4140
# Callers can be more specific by passing the right class
4241
ImageURL.new(**hash)
43-
when "file"
42+
when :file
4443
# Could be either - default to image for now
4544
ImageFile.new(**hash)
46-
when "text"
45+
when :text
4746
DocumentText.new(**hash)
4847
when nil
4948
# No type specified - try to infer

lib/active_agent/providers/anthropic/requests/thinking_config/_types.rb

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,13 @@ def cast(value)
1616
when Base
1717
value
1818
when Hash
19-
# Symbolize keys once for consistent lookups
20-
hash = value.symbolize_keys
21-
type = hash[:type]&.to_s
19+
hash = value.deep_symbolize_keys
20+
type = hash[:type]&.to_sym
2221

2322
case type
24-
when "enabled"
23+
when :enabled
2524
Enabled.new(**hash)
26-
when "disabled"
25+
when :disabled
2726
Disabled.new(**hash)
2827
when nil
2928
nil

lib/active_agent/providers/anthropic/requests/tool_choice/_types.rb

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,32 +18,31 @@ def cast(value)
1818
when Base
1919
value
2020
when Hash
21-
# Symbolize keys once for consistent lookups
22-
hash = value.symbolize_keys
23-
type = hash[:type]&.to_s
21+
hash = value.deep_symbolize_keys
22+
type = hash[:type]&.to_sym
2423

2524
case type
26-
when "auto"
25+
when :auto
2726
Auto.new(**hash)
28-
when "any"
27+
when :any
2928
Any.new(**hash)
30-
when "tool"
29+
when :tool
3130
Tool.new(**hash)
32-
when "none"
31+
when :none
3332
None.new(**hash)
3433
when nil
3534
nil
3635
else
3736
raise ArgumentError, "Unknown tool choice type: #{type}"
3837
end
39-
when String
38+
when String, Symbol
4039
# Allow string shortcuts like "auto", "any", "none"
41-
case value
42-
when "auto"
40+
case value.to_sym
41+
when :auto
4342
Auto.new
44-
when "any"
43+
when :any
4544
Any.new
46-
when "none"
45+
when :none
4746
None.new
4847
else
4948
raise ArgumentError, "Unknown tool choice: #{value}"
Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# frozen_string_literal: true
22

3+
require_relative "options"
34
require_relative "chat/_types"
45
require_relative "embedding/_types"
5-
6-
require_relative "options"

0 commit comments

Comments
 (0)