Skip to content

Commit 05b69d1

Browse files
authored
fix: structured output union decorations
1 parent 00b25bd commit 05b69d1

File tree

7 files changed

+40
-14
lines changed

7 files changed

+40
-14
lines changed

examples/structured_outputs_chat_completions.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class CalendarEvent < OpenAI::BaseModel
2929
doc: "Event location"
3030
end
3131

32-
# # gets API Key from environment variable `OPENAI_API_KEY`
32+
# gets API Key from environment variable `OPENAI_API_KEY`
3333
client = OpenAI::Client.new
3434

3535
chat_completion = client.chat.completions.create(

lib/openai/helpers/structured_output/union_of.rb

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,13 @@ def initialize(*variants)
4949
case variants
5050
in [Symbol => d, Hash => vs]
5151
discriminator(d)
52-
vs.each { variant(_1, _2) }
52+
vs.each do |k, v|
53+
v.is_a?(Proc) ? variant(k, v) : variant(k, -> { v })
54+
end
5355
else
54-
variants.each { variant(_1) }
56+
variants.each do |v|
57+
v.is_a?(Proc) ? variant(v) : variant(-> { v })
58+
end
5559
end
5660
end
5761
end

lib/openai/models/chat/completion_create_params.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ class CompletionCreateParams < OpenAI::Internal::Type::BaseModel
294294
# @return [Array<OpenAI::Chat::ChatCompletionTool, OpenAI::StructuredOutput::JsonSchemaConverter>, nil]
295295
optional :tools,
296296
-> {
297-
OpenAI::Internal::Type::ArrayOf[OpenAI::StructuredOutput::UnionOf[
297+
OpenAI::Internal::Type::ArrayOf[union: OpenAI::StructuredOutput::UnionOf[
298298
OpenAI::Chat::ChatCompletionTool, OpenAI::StructuredOutput::JsonSchemaConverter
299299
]]
300300
}

lib/openai/models/response_format_json_schema.rb

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,13 @@ class JSONSchema < OpenAI::Internal::Type::BaseModel
4848
# to build JSON schemas [here](https://json-schema.org/).
4949
#
5050
# @return [Hash{Symbol=>Object}, nil]
51-
optional :schema, OpenAI::Internal::Type::HashOf[OpenAI::Internal::Type::Unknown]
51+
optional :schema,
52+
union: -> {
53+
OpenAI::StructuredOutput::UnionOf[
54+
OpenAI::Internal::Type::HashOf[OpenAI::Internal::Type::Unknown],
55+
OpenAI::StructuredOutput::JsonSchemaConverter
56+
]
57+
}
5258

5359
# @!attribute strict
5460
# Whether to enable strict schema adherence when generating the output. If set to
@@ -70,7 +76,7 @@ class JSONSchema < OpenAI::Internal::Type::BaseModel
7076
#
7177
# @param description [String] A description of what the response format is for, used by the model to
7278
#
73-
# @param schema [Hash{Symbol=>Object}] The schema for the response format, described as a JSON Schema object.
79+
# @param schema [Hash{Symbol=>Object}, OpenAI::StructuredOutput::JsonSchemaConverter] The schema for the response format, described as a JSON Schema object.
7480
#
7581
# @param strict [Boolean, nil] Whether to enable strict schema adherence when generating the output.
7682
end

lib/openai/resources/chat/completions.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ def create(params)
108108
model = nil
109109
tool_models = {}
110110
case parsed
111-
in {response_format: OpenAI::Helpers::StructuredOutput::JsonSchemaConverter => model}
111+
in {response_format: OpenAI::StructuredOutput::JsonSchemaConverter => model}
112112
parsed.update(
113113
response_format: {
114114
type: :json_schema,
@@ -119,12 +119,12 @@ def create(params)
119119
}
120120
}
121121
)
122-
in {response_format: {type: :json_schema, json_schema: {schema: OpenAI::Helpers::StructuredOutput::JsonSchemaConverter => model}}}
122+
in {response_format: {type: :json_schema, json_schema: {schema: OpenAI::StructuredOutput::JsonSchemaConverter => model}}}
123123
parsed.dig(:response_format, :json_schema).store(:schema, model.to_json_schema)
124124
in {tools: Array => tools}
125125
mapped = tools.map do |tool|
126126
case tool
127-
in OpenAI::Helpers::StructuredOutput::JsonSchemaConverter
127+
in OpenAI::StructuredOutput::JsonSchemaConverter
128128
name = tool.name.split("::").last
129129
tool_models.store(name, tool)
130130
{
@@ -135,7 +135,7 @@ def create(params)
135135
parameters: tool.to_json_schema
136136
}
137137
}
138-
in {function: {parameters: OpenAI::Helpers::StructuredOutput::JsonSchemaConverter => params}}
138+
in {function: {parameters: OpenAI::StructuredOutput::JsonSchemaConverter => params}}
139139
func = tool.fetch(:function)
140140
name = func[:name] ||= params.name.split("::").last
141141
tool_models.store(name, params)
@@ -148,7 +148,7 @@ def create(params)
148148
end
149149

150150
unwrap = ->(raw) do
151-
if model.is_a?(OpenAI::Helpers::StructuredOutput::JsonSchemaConverter)
151+
if model.is_a?(OpenAI::StructuredOutput::JsonSchemaConverter)
152152
raw[:choices]&.each do |choice|
153153
message = choice.fetch(:message)
154154
parsed = JSON.parse(message.fetch(:content), symbolize_names: true)

rbi/openai/models/chat/completion_create_params.rbi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,7 @@ module OpenAI
468468
T.any(
469469
OpenAI::ResponseFormatText::OrHash,
470470
OpenAI::ResponseFormatJSONSchema::OrHash,
471+
OpenAI::StructuredOutput::JsonSchemaConverter,
471472
OpenAI::ResponseFormatJSONObject::OrHash
472473
),
473474
seed: T.nilable(Integer),

rbi/openai/models/response_format_json_schema.rbi

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,23 @@ module OpenAI
99
end
1010

1111
# Structured Outputs configuration options, including a JSON Schema.
12-
sig { returns(OpenAI::ResponseFormatJSONSchema::JSONSchema) }
12+
sig do
13+
returns(
14+
T.any(
15+
OpenAI::ResponseFormatJSONSchema::JSONSchema::OrHash,
16+
OpenAI::StructuredOutput::JsonSchemaConverter
17+
)
18+
)
19+
end
1320
attr_reader :json_schema
1421

1522
sig do
1623
params(
17-
json_schema: OpenAI::ResponseFormatJSONSchema::JSONSchema::OrHash
24+
json_schema:
25+
T.any(
26+
OpenAI::ResponseFormatJSONSchema::JSONSchema::OrHash,
27+
OpenAI::StructuredOutput::JsonSchemaConverter
28+
)
1829
).void
1930
end
2031
attr_writer :json_schema
@@ -28,7 +39,11 @@ module OpenAI
2839
# [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs).
2940
sig do
3041
params(
31-
json_schema: OpenAI::ResponseFormatJSONSchema::JSONSchema::OrHash,
42+
json_schema:
43+
T.any(
44+
OpenAI::ResponseFormatJSONSchema::JSONSchema::OrHash,
45+
OpenAI::StructuredOutput::JsonSchemaConverter
46+
),
3247
type: Symbol
3348
).returns(T.attached_class)
3449
end

0 commit comments

Comments
 (0)