Skip to content

release: 0.9.0 #159

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jun 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ on:
- 'integrated/**'
- 'stl-preview-head/**'
- 'stl-preview-base/**'
pull_request:
branches-ignore:
- 'stl-preview-head/**'
- 'stl-preview-base/**'

jobs:
lint:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish-gem.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Workflow for re-publishing to rubygems.org in case it failed for some reason.
# You can run this workflow by navigating to https://www.github.com/openai/openai-python/actions/workflows/publish-gem.yml
# You can run this workflow by navigating to https://www.github.com/openai/openai-ruby/actions/workflows/publish-gem.yml
name: Publish Gem
on:
workflow_dispatch:
Expand Down
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.8.0"
".": "0.9.0"
}
6 changes: 3 additions & 3 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 109
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai%2Fopenai-3ae9c18dd7ccfc3ac5206f24394665f563a19015cfa8847b2801a2694d012abc.yml
openapi_spec_hash: 48175b03b58805cd5c80793c66fd54e5
config_hash: 4caff63b74a41f71006987db702f2918
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai%2Fopenai-9e41d2d5471d2c28bff0d616f4476f5b0e6c541ef4cb51bdaaef5fdf5e13c8b2.yml
openapi_spec_hash: 86f765e18d00e32cf2ce9db7ab84d946
config_hash: dc5515e257676a27cb1ace1784aa92b3
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
# Changelog

## 0.9.0 (2025-06-17)

Full Changelog: [v0.8.0...v0.9.0](https://github.com/openai/openai-ruby/compare/v0.8.0...v0.9.0)

### Features

* **api:** add reusable prompt IDs ([72e35ad](https://github.com/openai/openai-ruby/commit/72e35ad4a677a70a98db291a20aa212e53c367ea))
* **api:** manual updates ([a4bcab7](https://github.com/openai/openai-ruby/commit/a4bcab736d59404c61b148a468d3bf0bc570fa39))


### Chores

* **ci:** enable for pull requests ([e8dfcf9](https://github.com/openai/openai-ruby/commit/e8dfcf97f3af426d3ad83472fa6eaac718acbd4d))
* **ci:** link to correct github repo ([7b34316](https://github.com/openai/openai-ruby/commit/7b3431612ea66d123bc114ec55bdf07f6081439e))


### Documentation

* structured outputs in README ([#723](https://github.com/openai/openai-ruby/issues/723)) ([7212e61](https://github.com/openai/openai-ruby/commit/7212e61ee2fb9ebff0576b0bff4424f43ae54af2))
* use image edit example in readme ([#722](https://github.com/openai/openai-ruby/issues/722)) ([eaa5055](https://github.com/openai/openai-ruby/commit/eaa5055eebca620c261c749ae4945845532c012d))

## 0.8.0 (2025-06-10)

Full Changelog: [v0.7.0...v0.8.0](https://github.com/openai/openai-ruby/compare/v0.7.0...v0.8.0)
Expand Down
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ GIT
PATH
remote: .
specs:
openai (0.8.0)
openai (0.9.0)
connection_pool

GEM
Expand Down
119 changes: 115 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ To use this gem, install via Bundler by adding the following to your application
<!-- x-release-please-start-version -->

```ruby
gem "openai", "~> 0.8.0"
gem "openai", "~> 0.9.0"
```

<!-- x-release-please-end -->
Expand Down Expand Up @@ -96,15 +96,126 @@ file_object = openai.files.create(file: Pathname("input.jsonl"), purpose: "fine-
# Alternatively, pass file contents or a `StringIO` directly:
file_object = openai.files.create(file: File.read("input.jsonl"), purpose: "fine-tune")

puts(file_object.id)

# Or, to control the filename and/or content type:
file = OpenAI::FilePart.new(File.read("input.jsonl"), filename: "input.jsonl", content_type: "…")
file_object = openai.files.create(file: file, purpose: "fine-tune")
image = OpenAI::FilePart.new(Pathname('dog.jpg'), content_type: 'image/jpeg')
edited = openai.images.edit(
prompt: "make this image look like a painting",
model: "gpt-image-1",
size: '1024x1024',
image: image
)

puts(file_object.id)
puts(edited.data.first)
```

Note that you can also pass a raw `IO` descriptor, but this disables retries, as the library can't be sure if the descriptor is a file or pipe (which cannot be rewound).

### [Structured outputs](https://platform.openai.com/docs/guides/structured-outputs) and function calling

This SDK ships with helpers in `OpenAI::BaseModel`, `OpenAI::ArrayOf`, `OpenAI::EnumOf`, and `OpenAI::UnionOf` to help you define the supported JSON schemas used in making structured outputs and function calling requests.

<details>
<summary>Snippet</summary>

```ruby
# Participant model with an optional last_name and an enum for status
class Participant < OpenAI::BaseModel
required :first_name, String
required :last_name, String, nil?: true
required :status, OpenAI::EnumOf[:confirmed, :unconfirmed, :tentative]
end

# CalendarEvent model with a list of participants.
class CalendarEvent < OpenAI::BaseModel
required :name, String
required :date, String
required :participants, OpenAI::ArrayOf[Participant]
end


client = OpenAI::Client.new

response = client.responses.create(
model: "gpt-4o-2024-08-06",
input: [
{role: :system, content: "Extract the event information."},
{
role: :user,
content: <<~CONTENT
Alice Shah and Lena are going to a science fair on Friday at 123 Main St. in San Diego.
They have also invited Jasper Vellani and Talia Groves - Jasper has not responded and Talia said she is thinking about it.
CONTENT
}
],
text: CalendarEvent
)

response
.output
.flat_map { _1.content }
# filter out refusal responses
.grep_v(OpenAI::Models::Responses::ResponseOutputRefusal)
.each do |content|
# parsed is an instance of `CalendarEvent`
pp(content.parsed)
end
```

</details>

See the [examples](https://github.com/openai/openai-ruby/tree/main/examples) directory for more usage examples for helper usage.

To make the equivalent request using raw JSON schema format, you would do the following:

<details>
<summary>Snippet</summary>

```ruby
response = client.responses.create(
model: "gpt-4o-2024-08-06",
input: [
{role: :system, content: "Extract the event information."},
{
role: :user,
content: "..."
}
],
text: {
format: {
type: :json_schema,
name: "CalendarEvent",
strict: true,
schema: {
type: "object",
properties: {
name: {type: "string"},
date: {type: "string"},
participants: {
type: "array",
items: {
type: "object",
properties: {
first_name: {type: "string"},
last_name: {type: %w[string null]},
status: {type: "string", enum: %w[confirmed unconfirmed tentative]}
},
required: %w[first_name last_name status],
additionalProperties: false
}
}
},
required: %w[name date participants],
additionalProperties: false
}
}
}
)
```

</details>

### Handling errors

When the library is unable to connect to the API, or if the API returns a non-success status code (i.e., 4xx or 5xx response), a subclass of `OpenAI::Errors::APIError` will be thrown:
Expand Down
1 change: 1 addition & 0 deletions examples/structured_outputs_chat_completions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,6 @@ class CalendarEvent < OpenAI::BaseModel
.choices
.reject { _1.message.refusal }
.each do |choice|
# parsed is an instance of `CalendarEvent`
pp(choice.message.parsed)
end
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,6 @@ class GetWeather < OpenAI::BaseModel
.reject { _1.message.refusal }
.flat_map { _1.message.tool_calls.to_a }
.each do |tool_call|
# parsed is an instance of `GetWeather`
pp(tool_call.function.parsed)
end
1 change: 1 addition & 0 deletions examples/structured_outputs_responses.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,6 @@ class CalendarEvent < OpenAI::BaseModel
# filter out refusal responses
.grep_v(OpenAI::Models::Responses::ResponseOutputRefusal)
.each do |content|
# parsed is an instance of `CalendarEvent`
pp(content.parsed)
end
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@ class GetWeather < OpenAI::BaseModel
response
.output
.each do |output|
# parsed is an instance of `GetWeather`
pp(output.parsed)
end
1 change: 1 addition & 0 deletions lib/openai.rb
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,7 @@
require_relative "openai/models/responses/response_output_refusal"
require_relative "openai/models/responses/response_output_text"
require_relative "openai/models/responses/response_output_text_annotation_added_event"
require_relative "openai/models/responses/response_prompt"
require_relative "openai/models/responses/response_queued_event"
require_relative "openai/models/responses/response_reasoning_delta_event"
require_relative "openai/models/responses/response_reasoning_done_event"
Expand Down
1 change: 1 addition & 0 deletions lib/openai/models/chat/chat_completion.rb
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ module ServiceTier
AUTO = :auto
DEFAULT = :default
FLEX = :flex
SCALE = :scale

# @!method self.values
# @return [Array<Symbol>]
Expand Down
1 change: 1 addition & 0 deletions lib/openai/models/chat/chat_completion_chunk.rb
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,7 @@ module ServiceTier
AUTO = :auto
DEFAULT = :default
FLEX = :flex
SCALE = :scale

# @!method self.values
# @return [Array<Symbol>]
Expand Down
1 change: 1 addition & 0 deletions lib/openai/models/chat/completion_create_params.rb
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,7 @@ module ServiceTier
AUTO = :auto
DEFAULT = :default
FLEX = :flex
SCALE = :scale

# @!method self.values
# @return [Array<Symbol>]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,76 +6,41 @@ module FineTuning
module Checkpoints
# @see OpenAI::Resources::FineTuning::Checkpoints::Permissions#retrieve
class PermissionRetrieveResponse < OpenAI::Internal::Type::BaseModel
# @!attribute data
# @!attribute id
# The permission identifier, which can be referenced in the API endpoints.
#
# @return [Array<OpenAI::Models::FineTuning::Checkpoints::PermissionRetrieveResponse::Data>]
required :data,
-> { OpenAI::Internal::Type::ArrayOf[OpenAI::Models::FineTuning::Checkpoints::PermissionRetrieveResponse::Data] }
# @return [String]
required :id, String

# @!attribute has_more
# @!attribute created_at
# The Unix timestamp (in seconds) for when the permission was created.
#
# @return [Boolean]
required :has_more, OpenAI::Internal::Type::Boolean
# @return [Integer]
required :created_at, Integer

# @!attribute object
# The object type, which is always "checkpoint.permission".
#
# @return [Symbol, :list]
required :object, const: :list
# @return [Symbol, :"checkpoint.permission"]
required :object, const: :"checkpoint.permission"

# @!attribute first_id
# @!attribute project_id
# The project identifier that the permission is for.
#
# @return [String, nil]
optional :first_id, String, nil?: true
# @return [String]
required :project_id, String

# @!attribute last_id
# @!method initialize(id:, created_at:, project_id:, object: :"checkpoint.permission")
# The `checkpoint.permission` object represents a permission for a fine-tuned
# model checkpoint.
#
# @return [String, nil]
optional :last_id, String, nil?: true

# @!method initialize(data:, has_more:, first_id: nil, last_id: nil, object: :list)
# @param data [Array<OpenAI::Models::FineTuning::Checkpoints::PermissionRetrieveResponse::Data>]
# @param has_more [Boolean]
# @param first_id [String, nil]
# @param last_id [String, nil]
# @param object [Symbol, :list]

class Data < OpenAI::Internal::Type::BaseModel
# @!attribute id
# The permission identifier, which can be referenced in the API endpoints.
#
# @return [String]
required :id, String

# @!attribute created_at
# The Unix timestamp (in seconds) for when the permission was created.
#
# @return [Integer]
required :created_at, Integer

# @!attribute object
# The object type, which is always "checkpoint.permission".
#
# @return [Symbol, :"checkpoint.permission"]
required :object, const: :"checkpoint.permission"

# @!attribute project_id
# The project identifier that the permission is for.
#
# @return [String]
required :project_id, String

# @!method initialize(id:, created_at:, project_id:, object: :"checkpoint.permission")
# The `checkpoint.permission` object represents a permission for a fine-tuned
# model checkpoint.
#
# @param id [String] The permission identifier, which can be referenced in the API endpoints.
#
# @param created_at [Integer] The Unix timestamp (in seconds) for when the permission was created.
#
# @param project_id [String] The project identifier that the permission is for.
#
# @param object [Symbol, :"checkpoint.permission"] The object type, which is always "checkpoint.permission".
end
# @param id [String] The permission identifier, which can be referenced in the API endpoints.
#
# @param created_at [Integer] The Unix timestamp (in seconds) for when the permission was created.
#
# @param project_id [String] The project identifier that the permission is for.
#
# @param object [Symbol, :"checkpoint.permission"] The object type, which is always "checkpoint.permission".
end
end
end
Expand Down
6 changes: 4 additions & 2 deletions lib/openai/models/fine_tuning/job_create_params.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ class JobCreateParams < OpenAI::Internal::Type::BaseModel
# [preference](https://platform.openai.com/docs/api-reference/fine-tuning/preference-input)
# format.
#
# See the [fine-tuning guide](https://platform.openai.com/docs/guides/fine-tuning)
# See the
# [fine-tuning guide](https://platform.openai.com/docs/guides/model-optimization)
# for more details.
#
# @return [String]
Expand Down Expand Up @@ -100,7 +101,8 @@ class JobCreateParams < OpenAI::Internal::Type::BaseModel
# Your dataset must be formatted as a JSONL file. You must upload your file with
# the purpose `fine-tune`.
#
# See the [fine-tuning guide](https://platform.openai.com/docs/guides/fine-tuning)
# See the
# [fine-tuning guide](https://platform.openai.com/docs/guides/model-optimization)
# for more details.
#
# @return [String, nil]
Expand Down
Loading