openai 0.78.0 → 0.79.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/CHANGELOG.md +80 -0
- data/README.md +241 -8
- data/SECURITY.md +6 -22
- data/azure.md +110 -0
- data/bedrock.md +132 -0
- data/examples/mtls_custom_http_client.rb +61 -0
- data/lib/openai/auth/workload_identity.rb +13 -2
- data/lib/openai/auth/workload_identity_auth.rb +2 -1
- data/lib/openai/client.rb +29 -6
- data/lib/openai/errors.rb +11 -1
- data/lib/openai/helpers/streaming/chat_completion_stream.rb +3 -3
- data/lib/openai/helpers/streaming/response_stream.rb +5 -6
- data/lib/openai/helpers/structured_output/base_model.rb +20 -19
- data/lib/openai/helpers/structured_output/json_schema_converter.rb +12 -5
- data/lib/openai/http_client.rb +99 -7
- data/lib/openai/internal/conversation_cursor_page.rb +5 -6
- data/lib/openai/internal/cursor_page.rb +3 -3
- data/lib/openai/internal/logging.rb +419 -0
- data/lib/openai/internal/next_cursor_page.rb +5 -6
- data/lib/openai/internal/page.rb +2 -2
- data/lib/openai/internal/provider.rb +7 -1
- data/lib/openai/internal/read_io_adapter.rb +42 -18
- data/lib/openai/internal/stream.rb +2 -2
- data/lib/openai/internal/transport/base_client.rb +137 -37
- data/lib/openai/internal/type/array_of.rb +6 -4
- data/lib/openai/internal/type/base_model.rb +39 -1
- data/lib/openai/internal/type/base_page.rb +19 -2
- data/lib/openai/internal/type/base_stream.rb +39 -7
- data/lib/openai/internal/type/hash_of.rb +3 -3
- data/lib/openai/internal/util.rb +52 -27
- data/lib/openai/models/admin/organization/audit_log_list_params.rb +3 -1
- data/lib/openai/models/admin/organization/audit_log_list_response.rb +33 -11
- data/lib/openai/models/admin/organization/groups/role_list_response.rb +5 -1
- data/lib/openai/models/admin/organization/groups/role_retrieve_response.rb +5 -1
- data/lib/openai/models/admin/organization/projects/groups/role_list_response.rb +6 -1
- data/lib/openai/models/admin/organization/projects/groups/role_retrieve_response.rb +6 -1
- data/lib/openai/models/admin/organization/projects/service_account_create_response.rb +3 -1
- data/lib/openai/models/admin/organization/projects/users/role_list_response.rb +6 -1
- data/lib/openai/models/admin/organization/projects/users/role_retrieve_response.rb +6 -1
- data/lib/openai/models/admin/organization/users/role_list_response.rb +5 -1
- data/lib/openai/models/admin/organization/users/role_retrieve_response.rb +5 -1
- data/lib/openai/models/all_models.rb +3 -0
- data/lib/openai/models/audio/transcription_create_params.rb +7 -1
- data/lib/openai/models/audio/translation_create_params.rb +7 -1
- data/lib/openai/models/beta/beta_response.rb +9 -0
- data/lib/openai/models/beta/beta_response_stream_event.rb +1 -1
- data/lib/openai/models/beta/beta_responses_client_event.rb +28 -3
- data/lib/openai/models/beta/beta_responses_server_event.rb +1037 -61
- data/lib/openai/models/beta/response_compact_params.rb +9 -0
- data/lib/openai/models/beta/response_create_params.rb +9 -0
- data/lib/openai/models/containers/file_create_params.rb +4 -0
- data/lib/openai/models/content_provenance_check_create_params.rb +4 -0
- data/lib/openai/models/file_create_params.rb +4 -0
- data/lib/openai/models/image_create_variation_params.rb +4 -0
- data/lib/openai/models/image_edit_params.rb +8 -0
- data/lib/openai/models/responses/response_compact_params.rb +9 -0
- data/lib/openai/models/responses/response_stream_event.rb +1 -1
- data/lib/openai/models/responses/responses_client_event.rb +13 -1
- data/lib/openai/models/responses/responses_server_event.rb +1027 -54
- data/lib/openai/models/responses_model.rb +3 -0
- data/lib/openai/models/skill_create_params.rb +4 -0
- data/lib/openai/models/skills/version_create_params.rb +4 -0
- data/lib/openai/models/uploads/part_create_params.rb +4 -0
- data/lib/openai/models/vector_store_search_response.rb +3 -1
- data/lib/openai/models/video_create_character_params.rb +4 -0
- data/lib/openai/models/video_create_params.rb +4 -0
- data/lib/openai/models/video_edit_params.rb +4 -0
- data/lib/openai/models/video_extend_params.rb +4 -0
- data/lib/openai/models.rb +9 -1
- data/lib/openai/net_http_client.rb +20 -6
- data/lib/openai/providers/azure.rb +216 -0
- data/lib/openai/providers/bedrock.rb +3 -1
- data/lib/openai/resources/admin/organization/projects/groups/roles.rb +1 -1
- data/lib/openai/resources/admin/organization/projects/groups.rb +1 -1
- data/lib/openai/resources/admin/organization/projects/users/roles.rb +1 -1
- data/lib/openai/resources/admin/organization/projects.rb +4 -2
- data/lib/openai/resources/audio/transcriptions.rb +8 -0
- data/lib/openai/resources/audio/translations.rb +4 -0
- data/lib/openai/resources/beta/responses.rb +1 -1
- data/lib/openai/resources/beta/threads/runs/steps.rb +2 -2
- data/lib/openai/resources/containers/files.rb +4 -0
- data/lib/openai/resources/content_provenance_checks.rb +4 -0
- data/lib/openai/resources/conversations/items.rb +1 -1
- data/lib/openai/resources/evals/runs/output_items.rb +1 -1
- data/lib/openai/resources/files.rb +4 -0
- data/lib/openai/resources/images.rb +12 -0
- data/lib/openai/resources/responses.rb +3 -2
- data/lib/openai/resources/skills/versions.rb +4 -0
- data/lib/openai/resources/skills.rb +4 -0
- data/lib/openai/resources/uploads/parts.rb +4 -0
- data/lib/openai/resources/vector_stores/file_batches.rb +1 -1
- data/lib/openai/resources/videos.rb +38 -0
- data/lib/openai/resources/webhooks.rb +18 -6
- data/lib/openai/version.rb +1 -1
- data/lib/openai.rb +111 -107
- data/rbi/openai/auth.rbi +4 -4
- data/rbi/openai/client.rbi +13 -3
- data/rbi/openai/errors.rbi +7 -0
- data/rbi/openai/helpers/streaming/events.rbi +12 -0
- data/rbi/openai/http_client.rbi +62 -2
- data/rbi/openai/internal/logging.rbi +192 -0
- data/rbi/openai/internal/provider.rbi +3 -0
- data/rbi/openai/internal/read_io_adapter.rbi +6 -1
- data/rbi/openai/internal/transport/base_client.rbi +61 -7
- data/rbi/openai/internal/type/base_model.rbi +24 -1
- data/rbi/openai/internal/type/base_page.rbi +13 -2
- data/rbi/openai/internal/type/base_stream.rbi +15 -4
- data/rbi/openai/internal/util.rbi +26 -2
- data/rbi/openai/models/admin/organization/audit_log_list_params.rbi +5 -0
- data/rbi/openai/models/admin/organization/audit_log_list_response.rbi +5 -0
- data/rbi/openai/models/all_models.rbi +15 -0
- data/rbi/openai/models/audio/transcription_create_params.rbi +14 -2
- data/rbi/openai/models/audio/translation_create_params.rbi +14 -2
- data/rbi/openai/models/beta/beta_response.rbi +15 -0
- data/rbi/openai/models/beta/beta_response_stream_event.rbi +1 -1
- data/rbi/openai/models/beta/beta_responses_client_event.rbi +37 -1
- data/rbi/openai/models/beta/beta_responses_server_event.rbi +3791 -54
- data/rbi/openai/models/beta/response_compact_params.rbi +15 -0
- data/rbi/openai/models/beta/response_create_params.rbi +15 -0
- data/rbi/openai/models/containers/file_create_params.rbi +8 -0
- data/rbi/openai/models/content_provenance_check_create_params.rbi +8 -0
- data/rbi/openai/models/file_create_params.rbi +8 -0
- data/rbi/openai/models/image_create_variation_params.rbi +8 -0
- data/rbi/openai/models/image_edit_params.rbi +16 -0
- data/rbi/openai/models/responses/response_compact_params.rbi +15 -0
- data/rbi/openai/models/responses/response_stream_event.rbi +1 -1
- data/rbi/openai/models/responses/responses_client_event.rbi +19 -0
- data/rbi/openai/models/responses/responses_server_event.rbi +3282 -53
- data/rbi/openai/models/responses_model.rbi +15 -0
- data/rbi/openai/models/skill_create_params.rbi +8 -0
- data/rbi/openai/models/skills/version_create_params.rbi +8 -0
- data/rbi/openai/models/uploads/part_create_params.rbi +8 -0
- data/rbi/openai/models/video_create_character_params.rbi +8 -0
- data/rbi/openai/models/video_create_params.rbi +8 -0
- data/rbi/openai/models/video_edit_params.rbi +8 -0
- data/rbi/openai/models/video_extend_params.rbi +8 -0
- data/rbi/openai/net_http_client.rbi +2 -2
- data/rbi/openai/providers.rbi +9 -0
- data/rbi/openai/resources/audio/transcriptions.rbi +14 -2
- data/rbi/openai/resources/audio/translations.rbi +7 -1
- data/rbi/openai/resources/containers/files.rbi +4 -0
- data/rbi/openai/resources/content_provenance_checks.rbi +4 -0
- data/rbi/openai/resources/files.rbi +4 -0
- data/rbi/openai/resources/images.rbi +20 -0
- data/rbi/openai/resources/skills/versions.rbi +4 -0
- data/rbi/openai/resources/skills.rbi +4 -0
- data/rbi/openai/resources/uploads/parts.rbi +4 -0
- data/rbi/openai/resources/videos.rbi +16 -0
- data/sig/openai/client.rbs +6 -2
- data/sig/openai/errors.rbs +5 -0
- data/sig/openai/http_client.rbs +37 -2
- data/sig/openai/internal/logging.rbs +88 -0
- data/sig/openai/internal/provider.rbs +3 -1
- data/sig/openai/internal/read_io_adapter.rbs +3 -1
- data/sig/openai/internal/transport/base_client.rbs +33 -5
- data/sig/openai/internal/type/base_model.rbs +13 -0
- data/sig/openai/internal/type/base_page.rbs +8 -1
- data/sig/openai/internal/type/base_stream.rbs +8 -2
- data/sig/openai/internal/util.rbs +12 -0
- data/sig/openai/models/admin/organization/audit_log_list_params.rbs +2 -0
- data/sig/openai/models/admin/organization/audit_log_list_response.rbs +2 -0
- data/sig/openai/models/all_models.rbs +6 -0
- data/sig/openai/models/beta/beta_response.rbs +6 -0
- data/sig/openai/models/beta/beta_responses_client_event.rbs +13 -0
- data/sig/openai/models/beta/beta_responses_server_event.rbs +1946 -54
- data/sig/openai/models/beta/response_compact_params.rbs +6 -0
- data/sig/openai/models/beta/response_create_params.rbs +6 -0
- data/sig/openai/models/responses/response_compact_params.rbs +6 -0
- data/sig/openai/models/responses/responses_client_event.rbs +7 -0
- data/sig/openai/models/responses/responses_server_event.rbs +1786 -53
- data/sig/openai/models/responses_model.rbs +6 -0
- data/sig/openai/net_http_client.rbs +2 -2
- data/sig/openai/providers.rbs +6 -0
- metadata +24 -1
|
@@ -28,6 +28,9 @@ module OpenAI
|
|
|
28
28
|
GPT_5_PRO = :"gpt-5-pro"
|
|
29
29
|
GPT_5_PRO_2025_10_06 = :"gpt-5-pro-2025-10-06"
|
|
30
30
|
GPT_5_1_CODEX_MAX = :"gpt-5.1-codex-max"
|
|
31
|
+
GPT_DAYBREAK_BLUE_LATEST = :"gpt-daybreak-blue-latest"
|
|
32
|
+
GPT_DAYBREAK_RED_LATEST = :"gpt-daybreak-red-latest"
|
|
33
|
+
GPT_5_6_CYBER = :"gpt-5.6-cyber"
|
|
31
34
|
|
|
32
35
|
# @!method self.values
|
|
33
36
|
# @return [Array<Symbol>]
|
|
@@ -10,6 +10,10 @@ module OpenAI
|
|
|
10
10
|
# @!attribute files
|
|
11
11
|
# Skill files to upload (directory upload) or a single zip file.
|
|
12
12
|
#
|
|
13
|
+
# `String`, `StringIO`, and pathless `IO` inputs are sent with generic upload
|
|
14
|
+
# metadata. Use `OpenAI::FilePart` when you need to override the filename or
|
|
15
|
+
# content type.
|
|
16
|
+
#
|
|
13
17
|
# @return [Array<Pathname, StringIO, IO, String, OpenAI::FilePart>, Pathname, StringIO, IO, String, OpenAI::FilePart, nil]
|
|
14
18
|
optional :files, union: -> { OpenAI::SkillCreateParams::Files }
|
|
15
19
|
|
|
@@ -22,6 +22,10 @@ module OpenAI
|
|
|
22
22
|
# @!attribute files
|
|
23
23
|
# Skill files to upload (directory upload) or a single zip file.
|
|
24
24
|
#
|
|
25
|
+
# `String`, `StringIO`, and pathless `IO` inputs are sent with generic upload
|
|
26
|
+
# metadata. Use `OpenAI::FilePart` when you need to override the filename or
|
|
27
|
+
# content type.
|
|
28
|
+
#
|
|
25
29
|
# @return [Array<Pathname, StringIO, IO, String, OpenAI::FilePart>, Pathname, StringIO, IO, String, OpenAI::FilePart, nil]
|
|
26
30
|
optional :files, union: -> { OpenAI::Skills::VersionCreateParams::Files }
|
|
27
31
|
|
|
@@ -16,6 +16,10 @@ module OpenAI
|
|
|
16
16
|
# @!attribute data
|
|
17
17
|
# The chunk of bytes for this Part.
|
|
18
18
|
#
|
|
19
|
+
# `String`, `StringIO`, and pathless `IO` inputs are sent with generic upload
|
|
20
|
+
# metadata. Use `OpenAI::FilePart` when you need to override the filename or
|
|
21
|
+
# content type.
|
|
22
|
+
#
|
|
19
23
|
# @return [Pathname, StringIO, IO, String, OpenAI::FilePart]
|
|
20
24
|
required :data, OpenAI::Internal::Type::FileInput
|
|
21
25
|
|
|
@@ -13,7 +13,9 @@ module OpenAI
|
|
|
13
13
|
#
|
|
14
14
|
# @return [Hash{Symbol=>String, Float, Boolean}, nil]
|
|
15
15
|
required :attributes,
|
|
16
|
-
-> {
|
|
16
|
+
-> {
|
|
17
|
+
OpenAI::Internal::Type::HashOf[union: OpenAI::Models::VectorStoreSearchResponse::Attribute]
|
|
18
|
+
},
|
|
17
19
|
nil?: true
|
|
18
20
|
|
|
19
21
|
# @!attribute content
|
|
@@ -16,6 +16,10 @@ module OpenAI
|
|
|
16
16
|
# @!attribute video
|
|
17
17
|
# Video file used to create a character.
|
|
18
18
|
#
|
|
19
|
+
# `String`, `StringIO`, and pathless `IO` inputs are sent with generic upload
|
|
20
|
+
# metadata. Use `OpenAI::FilePart` when you need to override the filename or
|
|
21
|
+
# content type.
|
|
22
|
+
#
|
|
19
23
|
# @return [Pathname, StringIO, IO, String, OpenAI::FilePart]
|
|
20
24
|
required :video, OpenAI::Internal::Type::FileInput
|
|
21
25
|
|
|
@@ -16,6 +16,10 @@ module OpenAI
|
|
|
16
16
|
# @!attribute input_reference
|
|
17
17
|
# Optional reference asset upload or reference object that guides generation.
|
|
18
18
|
#
|
|
19
|
+
# `String`, `StringIO`, and pathless `IO` inputs are sent with generic upload
|
|
20
|
+
# metadata. Use `OpenAI::FilePart` when you need to override the filename or
|
|
21
|
+
# content type.
|
|
22
|
+
#
|
|
19
23
|
# @return [Pathname, StringIO, IO, String, OpenAI::FilePart, OpenAI::Models::ImageInputReferenceParam, nil]
|
|
20
24
|
optional :input_reference, union: -> { OpenAI::VideoCreateParams::InputReference }
|
|
21
25
|
|
|
@@ -16,6 +16,10 @@ module OpenAI
|
|
|
16
16
|
# @!attribute video
|
|
17
17
|
# Reference to the completed video to edit.
|
|
18
18
|
#
|
|
19
|
+
# `String`, `StringIO`, and pathless `IO` inputs are sent with generic upload
|
|
20
|
+
# metadata. Use `OpenAI::FilePart` when you need to override the filename or
|
|
21
|
+
# content type.
|
|
22
|
+
#
|
|
19
23
|
# @return [Pathname, StringIO, IO, String, OpenAI::FilePart, OpenAI::Models::VideoEditParams::Video::VideoReferenceInputParam]
|
|
20
24
|
required :video, union: -> { OpenAI::VideoEditParams::Video }
|
|
21
25
|
|
|
@@ -23,6 +23,10 @@ module OpenAI
|
|
|
23
23
|
# @!attribute video
|
|
24
24
|
# Reference to the completed video to extend.
|
|
25
25
|
#
|
|
26
|
+
# `String`, `StringIO`, and pathless `IO` inputs are sent with generic upload
|
|
27
|
+
# metadata. Use `OpenAI::FilePart` when you need to override the filename or
|
|
28
|
+
# content type.
|
|
29
|
+
#
|
|
26
30
|
# @return [Pathname, StringIO, IO, String, OpenAI::FilePart, OpenAI::Models::VideoExtendParams::Video::VideoReferenceInputParam]
|
|
27
31
|
required :video, union: -> { OpenAI::VideoExtendParams::Video }
|
|
28
32
|
|
data/lib/openai/models.rb
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module OpenAI
|
|
4
|
-
|
|
4
|
+
# ActiveSupport 6 implements Class#subclasses using ==, which invokes BaseModel's
|
|
5
|
+
# structural equality before all model aliases are loaded.
|
|
6
|
+
base_model = OpenAI::Internal::Type::BaseModel
|
|
7
|
+
subclasses =
|
|
8
|
+
ObjectSpace.each_object(base_model.singleton_class).select do |candidate|
|
|
9
|
+
!candidate.singleton_class? && candidate.superclass.equal?(base_model)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
[base_model, *subclasses].each do |cls|
|
|
5
13
|
cls.define_sorbet_constant!(:OrHash) { T.type_alias { T.any(cls, OpenAI::Internal::AnyHash) } }
|
|
6
14
|
end
|
|
7
15
|
|
|
@@ -5,6 +5,10 @@ require_relative "internal/read_io_adapter"
|
|
|
5
5
|
module OpenAI
|
|
6
6
|
# The SDK's pooled Net::HTTP implementation.
|
|
7
7
|
#
|
|
8
|
+
# Network operations from a non-blocking fiber cooperate with its active Ruby
|
|
9
|
+
# Fiber scheduler, allowing concurrent requests and streams without occupying
|
|
10
|
+
# one thread per request.
|
|
11
|
+
#
|
|
8
12
|
# Pass a block to configure each SDK-created connection before it is pooled
|
|
9
13
|
# and started.
|
|
10
14
|
class NetHTTPClient < HTTPClient
|
|
@@ -66,15 +70,15 @@ module OpenAI
|
|
|
66
70
|
# @api private
|
|
67
71
|
#
|
|
68
72
|
# @param conn [Net::HTTP]
|
|
69
|
-
# @param deadline [Float]
|
|
73
|
+
# @param deadline [Float, nil]
|
|
70
74
|
private def calibrate_socket_timeout(conn, deadline)
|
|
71
|
-
timeout = remaining_timeout(
|
|
75
|
+
timeout = deadline&.then { remaining_timeout(_1) }
|
|
72
76
|
conn.open_timeout = conn.read_timeout = conn.write_timeout = conn.continue_timeout = timeout
|
|
73
77
|
end
|
|
74
78
|
|
|
75
79
|
# @api private
|
|
76
80
|
#
|
|
77
|
-
# @param deadline [Float]
|
|
81
|
+
# @param deadline [Float, nil]
|
|
78
82
|
# @return [Float]
|
|
79
83
|
# @raise [Timeout::Error]
|
|
80
84
|
private def remaining_timeout(deadline)
|
|
@@ -130,7 +134,6 @@ module OpenAI
|
|
|
130
134
|
# @yieldparam [Net::HTTP]
|
|
131
135
|
private def with_pool(url, deadline:, &blk)
|
|
132
136
|
origin = OpenAI::Internal::Util.uri_origin(url)
|
|
133
|
-
timeout = remaining_timeout(deadline)
|
|
134
137
|
pool =
|
|
135
138
|
@mutex.synchronize do
|
|
136
139
|
@pools[origin] ||= ConnectionPool.new(size: @size) do
|
|
@@ -138,7 +141,18 @@ module OpenAI
|
|
|
138
141
|
end
|
|
139
142
|
end
|
|
140
143
|
|
|
141
|
-
pool.with(timeout:
|
|
144
|
+
return pool.with(timeout: remaining_timeout(deadline), &blk) if deadline
|
|
145
|
+
|
|
146
|
+
checked_out = false
|
|
147
|
+
begin
|
|
148
|
+
pool.with do |connection|
|
|
149
|
+
checked_out = true
|
|
150
|
+
blk.call(connection)
|
|
151
|
+
end
|
|
152
|
+
rescue ConnectionPool::TimeoutError
|
|
153
|
+
retry unless checked_out
|
|
154
|
+
raise
|
|
155
|
+
end
|
|
142
156
|
end
|
|
143
157
|
|
|
144
158
|
# @api private
|
|
@@ -200,7 +214,7 @@ module OpenAI
|
|
|
200
214
|
# @return [OpenAI::HTTPClient::Response]
|
|
201
215
|
def execute(request)
|
|
202
216
|
url = request.url
|
|
203
|
-
deadline = OpenAI::Internal::Util.monotonic_secs +
|
|
217
|
+
deadline = request.timeout&.then { OpenAI::Internal::Util.monotonic_secs + _1 }
|
|
204
218
|
|
|
205
219
|
req = nil
|
|
206
220
|
finished = false
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module OpenAI
|
|
4
|
+
module Providers
|
|
5
|
+
# @api private
|
|
6
|
+
module Azure
|
|
7
|
+
API_KEY_AUTH_MARKER = :openai_azure_api_key
|
|
8
|
+
BEARER_AUTH_MARKER = :openai_azure_bearer
|
|
9
|
+
AUTH_HEADERS = %w[api-key authorization].freeze
|
|
10
|
+
MISSING_ENDPOINT_MESSAGE =
|
|
11
|
+
"Azure OpenAI requires an endpoint. Pass `endpoint` to `azure(...)`, or set " \
|
|
12
|
+
"`AZURE_OPENAI_ENDPOINT`."
|
|
13
|
+
MISSING_CREDENTIALS_MESSAGE =
|
|
14
|
+
"Could not find credentials for Azure OpenAI. Pass `api_key` or `token_provider` " \
|
|
15
|
+
"to `azure(...)`, or set `AZURE_OPENAI_API_KEY`."
|
|
16
|
+
|
|
17
|
+
class Definition
|
|
18
|
+
attr_reader :name
|
|
19
|
+
|
|
20
|
+
def initialize(base_url:, credential_provider:, authentication:)
|
|
21
|
+
@name = "azure"
|
|
22
|
+
@base_url = base_url.freeze
|
|
23
|
+
@credential_provider = credential_provider
|
|
24
|
+
@authentication = authentication
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def configure
|
|
28
|
+
auth = Auth.new(
|
|
29
|
+
base_url: @base_url,
|
|
30
|
+
credential_provider: @credential_provider,
|
|
31
|
+
authentication: @authentication
|
|
32
|
+
)
|
|
33
|
+
OpenAI::Internal::Provider::Runtime.new(
|
|
34
|
+
name: name,
|
|
35
|
+
base_url: @base_url,
|
|
36
|
+
prepare_request: auth.method(:prepare_request),
|
|
37
|
+
authentication_headers: AUTH_HEADERS
|
|
38
|
+
)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
class Auth
|
|
43
|
+
def initialize(base_url:, credential_provider:, authentication:)
|
|
44
|
+
@base_url = URI(base_url)
|
|
45
|
+
@credential_provider = credential_provider
|
|
46
|
+
@authentication = authentication
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def prepare_request(request)
|
|
50
|
+
Azure.validate_origin!(request.fetch(:url), @base_url)
|
|
51
|
+
marker = @authentication == :api_key ? API_KEY_AUTH_MARKER : BEARER_AUTH_MARKER
|
|
52
|
+
headers = Azure.provider_headers(request, marker: marker)
|
|
53
|
+
credential = resolve_credential
|
|
54
|
+
auth_header =
|
|
55
|
+
if @authentication == :api_key
|
|
56
|
+
{"api-key" => credential}
|
|
57
|
+
else
|
|
58
|
+
{"authorization" => "Bearer #{credential}"}
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
request.merge(headers: headers.merge(auth_header), provider_auth: marker)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
private def resolve_credential
|
|
65
|
+
credential = @credential_provider.call
|
|
66
|
+
unless credential.is_a?(String) && !credential.strip.empty?
|
|
67
|
+
name = @authentication == :api_key ? "API key" : "token provider"
|
|
68
|
+
raise OpenAI::Errors::Error,
|
|
69
|
+
"The Azure OpenAI #{name} must return a non-empty string."
|
|
70
|
+
end
|
|
71
|
+
credential
|
|
72
|
+
rescue OpenAI::Errors::Error
|
|
73
|
+
raise
|
|
74
|
+
rescue StandardError => e
|
|
75
|
+
message =
|
|
76
|
+
if @authentication == :api_key
|
|
77
|
+
"Failed to resolve an API key for Azure OpenAI."
|
|
78
|
+
else
|
|
79
|
+
"Failed to resolve a bearer token for Azure OpenAI."
|
|
80
|
+
end
|
|
81
|
+
raise OpenAI::Errors::Error.new(message), cause: e
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
class << self
|
|
86
|
+
def normalize_endpoint(endpoint)
|
|
87
|
+
uri = URI(endpoint)
|
|
88
|
+
unless uri.is_a?(URI::HTTP) && uri.host
|
|
89
|
+
raise ArgumentError, "The Azure OpenAI `endpoint` must be an absolute HTTP or HTTPS URL."
|
|
90
|
+
end
|
|
91
|
+
unless uri.query.nil?
|
|
92
|
+
raise ArgumentError, "The Azure OpenAI `endpoint` must not include a query string."
|
|
93
|
+
end
|
|
94
|
+
unless uri.fragment.nil?
|
|
95
|
+
raise ArgumentError, "The Azure OpenAI `endpoint` must not include a fragment."
|
|
96
|
+
end
|
|
97
|
+
unless uri.userinfo.nil?
|
|
98
|
+
raise ArgumentError, "The Azure OpenAI `endpoint` must not include user information."
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
path = uri.path.sub(%r{/+\z}, "")
|
|
102
|
+
uri.path =
|
|
103
|
+
case path
|
|
104
|
+
when %r{/openai/v1\z}
|
|
105
|
+
path
|
|
106
|
+
when %r{/openai\z}
|
|
107
|
+
"#{path}/v1"
|
|
108
|
+
else
|
|
109
|
+
"#{path}/openai/v1"
|
|
110
|
+
end
|
|
111
|
+
uri.to_s
|
|
112
|
+
rescue URI::InvalidURIError => e
|
|
113
|
+
message = "The Azure OpenAI `endpoint` must be an absolute HTTP or HTTPS URL."
|
|
114
|
+
raise ArgumentError.new(message), cause: e
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def normalize_optional_string(value)
|
|
118
|
+
return nil unless value.is_a?(String)
|
|
119
|
+
normalized = value.strip
|
|
120
|
+
normalized unless normalized.empty?
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def provider_headers(request, marker:)
|
|
124
|
+
headers = request.fetch(:headers).dup
|
|
125
|
+
if request[:provider_auth] == marker
|
|
126
|
+
AUTH_HEADERS.each { headers.delete(_1) }
|
|
127
|
+
elsif AUTH_HEADERS.any? { headers.key?(_1) }
|
|
128
|
+
raise OpenAI::Errors::Error,
|
|
129
|
+
"Azure OpenAI provider authentication cannot be combined with a custom " \
|
|
130
|
+
"`Authorization` or `api-key` header."
|
|
131
|
+
end
|
|
132
|
+
headers
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def validate_origin!(url, base_url)
|
|
136
|
+
return if OpenAI::Internal::Util.uri_origin(url) == OpenAI::Internal::Util.uri_origin(base_url)
|
|
137
|
+
raise OpenAI::Errors::Error,
|
|
138
|
+
"Refusing to authenticate a request for an origin other than the configured " \
|
|
139
|
+
"Azure OpenAI endpoint."
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
class << self
|
|
145
|
+
# Configure the standard OpenAI client for the Azure OpenAI v1 API.
|
|
146
|
+
#
|
|
147
|
+
# @param endpoint [String, nil] Azure OpenAI resource endpoint. Defaults to
|
|
148
|
+
# `AZURE_OPENAI_ENDPOINT`. `/openai/v1` is appended when absent.
|
|
149
|
+
#
|
|
150
|
+
# @param api_key [String, nil] Azure OpenAI API key. Defaults to
|
|
151
|
+
# `AZURE_OPENAI_API_KEY` when no token provider is configured. Passing
|
|
152
|
+
# `nil` explicitly skips the environment fallback.
|
|
153
|
+
#
|
|
154
|
+
# @param token_provider [#call, nil] Callable returning a Microsoft Entra
|
|
155
|
+
# bearer token before each request attempt.
|
|
156
|
+
#
|
|
157
|
+
# @return [OpenAI::Provider]
|
|
158
|
+
def azure(
|
|
159
|
+
endpoint: OpenAI::Internal::OMIT,
|
|
160
|
+
api_key: OpenAI::Internal::OMIT,
|
|
161
|
+
token_provider: nil
|
|
162
|
+
)
|
|
163
|
+
configured_endpoint =
|
|
164
|
+
if endpoint.equal?(OpenAI::Internal::OMIT)
|
|
165
|
+
Azure.normalize_optional_string(ENV["AZURE_OPENAI_ENDPOINT"])
|
|
166
|
+
else
|
|
167
|
+
normalized = Azure.normalize_optional_string(endpoint)
|
|
168
|
+
if !endpoint.nil? && normalized.nil?
|
|
169
|
+
raise ArgumentError, "The Azure OpenAI `endpoint` must not be empty."
|
|
170
|
+
end
|
|
171
|
+
normalized
|
|
172
|
+
end
|
|
173
|
+
raise ArgumentError, Azure::MISSING_ENDPOINT_MESSAGE if configured_endpoint.nil?
|
|
174
|
+
base_url = Azure.normalize_endpoint(configured_endpoint)
|
|
175
|
+
|
|
176
|
+
explicit_api_key = !api_key.equal?(OpenAI::Internal::OMIT) && !api_key.nil?
|
|
177
|
+
normalized_api_key = Azure.normalize_optional_string(api_key)
|
|
178
|
+
if explicit_api_key && normalized_api_key.nil?
|
|
179
|
+
raise ArgumentError, "The Azure OpenAI API key must not be empty."
|
|
180
|
+
end
|
|
181
|
+
unless token_provider.nil? || token_provider.respond_to?(:call)
|
|
182
|
+
raise ArgumentError, "The Azure OpenAI `token_provider` must respond to `call`."
|
|
183
|
+
end
|
|
184
|
+
if explicit_api_key && !token_provider.nil?
|
|
185
|
+
raise ArgumentError,
|
|
186
|
+
"The Azure OpenAI `api_key` and `token_provider` options are mutually exclusive."
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
environment_api_key =
|
|
190
|
+
if api_key.equal?(OpenAI::Internal::OMIT) && token_provider.nil?
|
|
191
|
+
Azure.normalize_optional_string(ENV["AZURE_OPENAI_API_KEY"])
|
|
192
|
+
end
|
|
193
|
+
resolved_api_key = normalized_api_key || environment_api_key
|
|
194
|
+
if resolved_api_key.nil? && token_provider.nil?
|
|
195
|
+
raise ArgumentError, Azure::MISSING_CREDENTIALS_MESSAGE
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
if token_provider
|
|
199
|
+
credential_provider = token_provider
|
|
200
|
+
authentication = :bearer
|
|
201
|
+
else
|
|
202
|
+
resolved_api_key.freeze
|
|
203
|
+
credential_provider = -> { resolved_api_key }
|
|
204
|
+
authentication = :api_key
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
definition = Azure::Definition.new(
|
|
208
|
+
base_url: base_url,
|
|
209
|
+
credential_provider: credential_provider,
|
|
210
|
+
authentication: authentication
|
|
211
|
+
)
|
|
212
|
+
OpenAI::Internal::Provider.create(definition)
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
end
|
|
@@ -6,6 +6,7 @@ module OpenAI
|
|
|
6
6
|
module Bedrock
|
|
7
7
|
SERVICE = "bedrock-mantle"
|
|
8
8
|
CANONICAL_HOST = /\Abedrock-mantle\.([a-z0-9-]+)\.api\.aws\z/i
|
|
9
|
+
AUTH_HEADERS = %w[authorization].freeze
|
|
9
10
|
SIGNING_HEADERS = %w[authorization x-amz-content-sha256 x-amz-date x-amz-security-token].freeze
|
|
10
11
|
BEARER_AUTH_MARKER = :openai_bedrock_bearer
|
|
11
12
|
SIGV4_AUTH_MARKER = :openai_bedrock_sigv4
|
|
@@ -91,7 +92,8 @@ module OpenAI
|
|
|
91
92
|
OpenAI::Internal::Provider::Runtime.new(
|
|
92
93
|
name: name,
|
|
93
94
|
base_url: base_url,
|
|
94
|
-
prepare_request: auth.method(:prepare_request)
|
|
95
|
+
prepare_request: auth.method(:prepare_request),
|
|
96
|
+
authentication_headers: AUTH_HEADERS
|
|
95
97
|
)
|
|
96
98
|
end
|
|
97
99
|
end
|
|
@@ -97,11 +97,11 @@ module OpenAI
|
|
|
97
97
|
# @see OpenAI::Models::Admin::Organization::Projects::Groups::RoleListParams
|
|
98
98
|
def list(group_id, params)
|
|
99
99
|
parsed, options = OpenAI::Admin::Organization::Projects::Groups::RoleListParams.dump_request(params)
|
|
100
|
-
query = OpenAI::Internal::Util.encode_query_params(parsed)
|
|
101
100
|
project_id =
|
|
102
101
|
parsed.delete(:project_id) do
|
|
103
102
|
raise ArgumentError.new("missing required path argument #{_1}")
|
|
104
103
|
end
|
|
104
|
+
query = OpenAI::Internal::Util.encode_query_params(parsed)
|
|
105
105
|
@client.request(
|
|
106
106
|
method: :get,
|
|
107
107
|
path: ["projects/%1$s/groups/%2$s/roles", project_id, group_id],
|
|
@@ -53,11 +53,11 @@ module OpenAI
|
|
|
53
53
|
# @see OpenAI::Models::Admin::Organization::Projects::GroupRetrieveParams
|
|
54
54
|
def retrieve(group_id, params)
|
|
55
55
|
parsed, options = OpenAI::Admin::Organization::Projects::GroupRetrieveParams.dump_request(params)
|
|
56
|
-
query = OpenAI::Internal::Util.encode_query_params(parsed)
|
|
57
56
|
project_id =
|
|
58
57
|
parsed.delete(:project_id) do
|
|
59
58
|
raise ArgumentError.new("missing required path argument #{_1}")
|
|
60
59
|
end
|
|
60
|
+
query = OpenAI::Internal::Util.encode_query_params(parsed)
|
|
61
61
|
@client.request(
|
|
62
62
|
method: :get,
|
|
63
63
|
path: ["organization/projects/%1$s/groups/%2$s", project_id, group_id],
|
|
@@ -97,11 +97,11 @@ module OpenAI
|
|
|
97
97
|
# @see OpenAI::Models::Admin::Organization::Projects::Users::RoleListParams
|
|
98
98
|
def list(user_id, params)
|
|
99
99
|
parsed, options = OpenAI::Admin::Organization::Projects::Users::RoleListParams.dump_request(params)
|
|
100
|
-
query = OpenAI::Internal::Util.encode_query_params(parsed)
|
|
101
100
|
project_id =
|
|
102
101
|
parsed.delete(:project_id) do
|
|
103
102
|
raise ArgumentError.new("missing required path argument #{_1}")
|
|
104
103
|
end
|
|
104
|
+
query = OpenAI::Internal::Util.encode_query_params(parsed)
|
|
105
105
|
@client.request(
|
|
106
106
|
method: :get,
|
|
107
107
|
path: ["projects/%1$s/users/%2$s/roles", project_id, user_id],
|
|
@@ -182,7 +182,8 @@ module OpenAI
|
|
|
182
182
|
def initialize(client:)
|
|
183
183
|
@client = client
|
|
184
184
|
@users = OpenAI::Resources::Admin::Organization::Projects::Users.new(client: client)
|
|
185
|
-
@service_accounts =
|
|
185
|
+
@service_accounts =
|
|
186
|
+
OpenAI::Resources::Admin::Organization::Projects::ServiceAccounts.new(client: client)
|
|
186
187
|
@api_keys = OpenAI::Resources::Admin::Organization::Projects::APIKeys.new(client: client)
|
|
187
188
|
@rate_limits = OpenAI::Resources::Admin::Organization::Projects::RateLimits.new(client: client)
|
|
188
189
|
@model_permissions =
|
|
@@ -191,7 +192,8 @@ module OpenAI
|
|
|
191
192
|
OpenAI::Resources::Admin::Organization::Projects::HostedToolPermissions.new(client: client)
|
|
192
193
|
@groups = OpenAI::Resources::Admin::Organization::Projects::Groups.new(client: client)
|
|
193
194
|
@roles = OpenAI::Resources::Admin::Organization::Projects::Roles.new(client: client)
|
|
194
|
-
@data_retention =
|
|
195
|
+
@data_retention =
|
|
196
|
+
OpenAI::Resources::Admin::Organization::Projects::DataRetention.new(client: client)
|
|
195
197
|
@spend_limit = OpenAI::Resources::Admin::Organization::Projects::SpendLimit.new(client: client)
|
|
196
198
|
@spend_alerts = OpenAI::Resources::Admin::Organization::Projects::SpendAlerts.new(client: client)
|
|
197
199
|
@certificates = OpenAI::Resources::Admin::Organization::Projects::Certificates.new(client: client)
|
|
@@ -16,6 +16,10 @@ module OpenAI
|
|
|
16
16
|
# Returns a transcription object in `json`, `diarized_json`, or `verbose_json`
|
|
17
17
|
# format, or a stream of transcript events.
|
|
18
18
|
#
|
|
19
|
+
# `String`, `StringIO`, and pathless `IO` inputs are sent with generic upload
|
|
20
|
+
# metadata. Use `OpenAI::FilePart` when you need to override the filename or
|
|
21
|
+
# content type.
|
|
22
|
+
#
|
|
19
23
|
# @overload create(file:, model:, chunking_strategy: nil, include: nil, keywords: nil, known_speaker_names: nil, known_speaker_references: nil, language: nil, languages: nil, prompt: nil, response_format: nil, temperature: nil, timestamp_granularities: nil, request_options: {})
|
|
20
24
|
#
|
|
21
25
|
# @param file [Pathname, StringIO, IO, String, OpenAI::FilePart] The audio file object (not file name) to transcribe, in one of these formats: fl
|
|
@@ -77,6 +81,10 @@ module OpenAI
|
|
|
77
81
|
# Returns a transcription object in `json`, `diarized_json`, or `verbose_json`
|
|
78
82
|
# format, or a stream of transcript events.
|
|
79
83
|
#
|
|
84
|
+
# `String`, `StringIO`, and pathless `IO` inputs are sent with generic upload
|
|
85
|
+
# metadata. Use `OpenAI::FilePart` when you need to override the filename or
|
|
86
|
+
# content type.
|
|
87
|
+
#
|
|
80
88
|
# @overload create_streaming(file:, model:, chunking_strategy: nil, include: nil, keywords: nil, known_speaker_names: nil, known_speaker_references: nil, language: nil, languages: nil, prompt: nil, response_format: nil, temperature: nil, timestamp_granularities: nil, request_options: {})
|
|
81
89
|
#
|
|
82
90
|
# @param file [Pathname, StringIO, IO, String, OpenAI::FilePart] The audio file object (not file name) to transcribe, in one of these formats: fl
|
|
@@ -10,6 +10,10 @@ module OpenAI
|
|
|
10
10
|
#
|
|
11
11
|
# Translates audio into English.
|
|
12
12
|
#
|
|
13
|
+
# `String`, `StringIO`, and pathless `IO` inputs are sent with generic upload
|
|
14
|
+
# metadata. Use `OpenAI::FilePart` when you need to override the filename or
|
|
15
|
+
# content type.
|
|
16
|
+
#
|
|
13
17
|
# @overload create(file:, model:, prompt: nil, response_format: nil, temperature: nil, request_options: {})
|
|
14
18
|
#
|
|
15
19
|
# @param file [Pathname, StringIO, IO, String, OpenAI::FilePart] The audio file object (not file name) translate, in one of these formats: flac,
|
|
@@ -301,12 +301,12 @@ module OpenAI
|
|
|
301
301
|
def retrieve_streaming(response_id, params = {})
|
|
302
302
|
query_params = [:include, :include_obfuscation, :starting_after, :stream]
|
|
303
303
|
parsed, options = OpenAI::Beta::ResponseRetrieveParams.dump_request(params)
|
|
304
|
-
query = OpenAI::Internal::Util.encode_query_params(parsed.slice(*query_params))
|
|
305
304
|
unless parsed.fetch(:stream, true)
|
|
306
305
|
message = "Please use `#retrieve` for the non-streaming use case."
|
|
307
306
|
raise ArgumentError.new(message)
|
|
308
307
|
end
|
|
309
308
|
parsed.store(:stream, true)
|
|
309
|
+
query = OpenAI::Internal::Util.encode_query_params(parsed.slice(*query_params))
|
|
310
310
|
@client.request(
|
|
311
311
|
method: :get,
|
|
312
312
|
path: ["responses/%1$s?beta=true", response_id],
|
|
@@ -33,7 +33,6 @@ module OpenAI
|
|
|
33
33
|
# @see OpenAI::Models::Beta::Threads::Runs::StepRetrieveParams
|
|
34
34
|
def retrieve(step_id, params)
|
|
35
35
|
parsed, options = OpenAI::Beta::Threads::Runs::StepRetrieveParams.dump_request(params)
|
|
36
|
-
query = OpenAI::Internal::Util.encode_query_params(parsed)
|
|
37
36
|
thread_id =
|
|
38
37
|
parsed.delete(:thread_id) do
|
|
39
38
|
raise ArgumentError.new("missing required path argument #{_1}")
|
|
@@ -42,6 +41,7 @@ module OpenAI
|
|
|
42
41
|
parsed.delete(:run_id) do
|
|
43
42
|
raise ArgumentError.new("missing required path argument #{_1}")
|
|
44
43
|
end
|
|
44
|
+
query = OpenAI::Internal::Util.encode_query_params(parsed)
|
|
45
45
|
@client.request(
|
|
46
46
|
method: :get,
|
|
47
47
|
path: ["threads/%1$s/runs/%2$s/steps/%3$s", thread_id, run_id, step_id],
|
|
@@ -82,11 +82,11 @@ module OpenAI
|
|
|
82
82
|
# @see OpenAI::Models::Beta::Threads::Runs::StepListParams
|
|
83
83
|
def list(run_id, params)
|
|
84
84
|
parsed, options = OpenAI::Beta::Threads::Runs::StepListParams.dump_request(params)
|
|
85
|
-
query = OpenAI::Internal::Util.encode_query_params(parsed)
|
|
86
85
|
thread_id =
|
|
87
86
|
parsed.delete(:thread_id) do
|
|
88
87
|
raise ArgumentError.new("missing required path argument #{_1}")
|
|
89
88
|
end
|
|
89
|
+
query = OpenAI::Internal::Util.encode_query_params(parsed)
|
|
90
90
|
@client.request(
|
|
91
91
|
method: :get,
|
|
92
92
|
path: ["threads/%1$s/runs/%2$s/steps", thread_id, run_id],
|
|
@@ -15,6 +15,10 @@ module OpenAI
|
|
|
15
15
|
# You can send either a multipart/form-data request with the raw file content, or
|
|
16
16
|
# a JSON request with a file ID.
|
|
17
17
|
#
|
|
18
|
+
# `String`, `StringIO`, and pathless `IO` inputs are sent with generic upload
|
|
19
|
+
# metadata. Use `OpenAI::FilePart` when you need to override the filename or
|
|
20
|
+
# content type.
|
|
21
|
+
#
|
|
18
22
|
# @overload create(container_id, file: nil, file_id: nil, request_options: {})
|
|
19
23
|
#
|
|
20
24
|
# @param container_id [String]
|
|
@@ -13,6 +13,10 @@ module OpenAI
|
|
|
13
13
|
# signals were available. Content could also still be AI-generated by another
|
|
14
14
|
# company's model, which the tool currently does not detect.
|
|
15
15
|
#
|
|
16
|
+
# `String`, `StringIO`, and pathless `IO` inputs are sent with generic upload
|
|
17
|
+
# metadata. Use `OpenAI::FilePart` when you need to override the filename or
|
|
18
|
+
# content type.
|
|
19
|
+
#
|
|
16
20
|
# @overload create(file:, request_options: {})
|
|
17
21
|
#
|
|
18
22
|
# @param file [Pathname, StringIO, IO, String, OpenAI::FilePart] The image or audio file to check for supported OpenAI provenance signals.
|
|
@@ -58,11 +58,11 @@ module OpenAI
|
|
|
58
58
|
# @see OpenAI::Models::Conversations::ItemRetrieveParams
|
|
59
59
|
def retrieve(item_id, params)
|
|
60
60
|
parsed, options = OpenAI::Conversations::ItemRetrieveParams.dump_request(params)
|
|
61
|
-
query = OpenAI::Internal::Util.encode_query_params(parsed)
|
|
62
61
|
conversation_id =
|
|
63
62
|
parsed.delete(:conversation_id) do
|
|
64
63
|
raise ArgumentError.new("missing required path argument #{_1}")
|
|
65
64
|
end
|
|
65
|
+
query = OpenAI::Internal::Util.encode_query_params(parsed)
|
|
66
66
|
@client.request(
|
|
67
67
|
method: :get,
|
|
68
68
|
path: ["conversations/%1$s/items/%2$s", conversation_id, item_id],
|
|
@@ -66,11 +66,11 @@ module OpenAI
|
|
|
66
66
|
# @see OpenAI::Models::Evals::Runs::OutputItemListParams
|
|
67
67
|
def list(run_id, params)
|
|
68
68
|
parsed, options = OpenAI::Evals::Runs::OutputItemListParams.dump_request(params)
|
|
69
|
-
query = OpenAI::Internal::Util.encode_query_params(parsed)
|
|
70
69
|
eval_id =
|
|
71
70
|
parsed.delete(:eval_id) do
|
|
72
71
|
raise ArgumentError.new("missing required path argument #{_1}")
|
|
73
72
|
end
|
|
73
|
+
query = OpenAI::Internal::Util.encode_query_params(parsed)
|
|
74
74
|
@client.request(
|
|
75
75
|
method: :get,
|
|
76
76
|
path: ["evals/%1$s/runs/%2$s/output_items", eval_id, run_id],
|
|
@@ -36,6 +36,10 @@ module OpenAI
|
|
|
36
36
|
# Please [contact us](https://help.openai.com/) if you need to increase these
|
|
37
37
|
# storage limits.
|
|
38
38
|
#
|
|
39
|
+
# `String`, `StringIO`, and pathless `IO` inputs are sent with generic upload
|
|
40
|
+
# metadata. Use `OpenAI::FilePart` when you need to override the filename or
|
|
41
|
+
# content type.
|
|
42
|
+
#
|
|
39
43
|
# @overload create(file:, purpose:, expires_after: nil, request_options: {})
|
|
40
44
|
#
|
|
41
45
|
# @param file [Pathname, StringIO, IO, String, OpenAI::FilePart] The File object (not file name) to be uploaded.
|