Skip to content

Commit fd1a4e1

Browse files
chore: documentation improvements
1 parent b57f840 commit fd1a4e1

File tree

3 files changed

+81
-89
lines changed

3 files changed

+81
-89
lines changed

README.md

Lines changed: 79 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,26 @@ openai = OpenAI::Client.new(
3131
)
3232

3333
chat_completion = openai.chat.completions.create(
34-
messages: [{
35-
role: "user",
36-
content: "Say this is a test"
37-
}],
38-
model: "gpt-4o"
34+
messages: [{role: :user, content: "Say this is a test"}],
35+
model: :"gpt-4.1"
3936
)
4037

4138
puts(chat_completion)
4239
```
4340

41+
## Sorbet
42+
43+
This library is written with [Sorbet type definitions](https://sorbet.org/docs/rbi). However, there is no runtime dependency on the `sorbet-runtime`.
44+
45+
When using sorbet, it is recommended to use model classes as below. This provides stronger type checking and tooling integration.
46+
47+
```ruby
48+
openai.chat.completions.create(
49+
messages: [OpenAI::Models::Chat::ChatCompletionUserMessageParam.new(role: :user, content: "Say this is a test")],
50+
model: :"gpt-4.1"
51+
)
52+
```
53+
4454
### Pagination
4555

4656
List methods in the OpenAI API are paginated.
@@ -68,11 +78,8 @@ We provide support for streaming responses using Server-Sent Events (SSE).
6878

6979
```ruby
7080
stream = openai.chat.completions.stream_raw(
71-
messages: [{
72-
role: "user",
73-
content: "Say this is a test"
74-
}],
75-
model: "gpt-4o"
81+
messages: [{role: :user, content: "Say this is a test"}],
82+
model: :"gpt-4.1"
7683
)
7784

7885
stream.each do |completion|
@@ -88,11 +95,11 @@ Request parameters that correspond to file uploads can be passed as `StringIO`,
8895
require "pathname"
8996

9097
# using `Pathname`, the file will be lazily read, without reading everything in to memory
91-
file_object = openai.files.create(file: Pathname("input.jsonl"), purpose: "fine-tune")
98+
file_object = openai.files.create(file: Pathname("input.jsonl"), purpose: :"fine-tune")
9299

93100
file = File.read("input.jsonl")
94101
# using `StringIO`, useful if you already have the data in memory
95-
file_object = openai.files.create(file: StringIO.new(file), purpose: "fine-tune")
102+
file_object = openai.files.create(file: StringIO.new(file), purpose: :"fine-tune")
96103

97104
puts(file_object.id)
98105
```
@@ -103,7 +110,7 @@ When the library is unable to connect to the API, or if the API returns a non-su
103110

104111
```ruby
105112
begin
106-
job = openai.fine_tuning.jobs.create(model: "gpt-4o", training_file: "file-abc123")
113+
job = openai.fine_tuning.jobs.create(model: :"babbage-002", training_file: "file-abc123")
107114
rescue OpenAI::Errors::APIError => e
108115
puts(e.status) # 400
109116
end
@@ -141,11 +148,8 @@ openai = OpenAI::Client.new(
141148

142149
# Or, configure per-request:
143150
openai.chat.completions.create(
144-
messages: [{
145-
role: "user",
146-
content: "How can I get the name of the current day in JavaScript?"
147-
}],
148-
model: "gpt-4o",
151+
messages: [{role: :user, content: "How can I get the name of the current day in JavaScript?"}],
152+
model: :"gpt-4.1",
149153
request_options: {max_retries: 5}
150154
)
151155
```
@@ -166,78 +170,44 @@ openai = OpenAI::Client.new(
166170

167171
# Or, configure per-request:
168172
openai.chat.completions.create(
169-
messages: [{
170-
role: "user",
171-
content: "How can I list all files in a directory using Python?"
172-
}],
173-
model: "gpt-4o",
173+
messages: [{role: :user, content: "How can I list all files in a directory using Python?"}],
174+
model: :"gpt-4.1",
174175
request_options: {timeout: 5}
175176
)
176177
```
177178

178-
## LSP Support
179+
## Editor support
179180

180-
### Solargraph
181+
Some editor language services like [Solargraph](https://github.com/castwide/solargraph?tab=readme-ov-file#gem-support) or [Sorbet](https://sorbet.org/docs/rbi#the-hidden-definitions-rbi) require a manually triggered indexing step before functionalities like auto-completion and go to definition can operate.
181182

182-
This library includes [Solargraph](https://solargraph.org) support for both auto completion and go to definition.
183+
Please refer to their respective documentation for details. This library also includes a [short guide](https://github.com/openai/openai-ruby/tree/main/CONTRIBUTING.md#editor-support) on how to set up various editor services for internal development.
183184

184-
```ruby
185-
gem "solargraph", group: :development
186-
```
185+
## Advanced Concepts
187186

188-
After Solargraph is installed, **you must populate its index** either via the provided editor command, or by running the following in your terminal:
187+
### Model DSL
189188

190-
```sh
191-
bundle exec solargraph gems
192-
```
189+
This library uses a Model DSL to represent request parameters and response shapes in `lib/openai/models`.
193190

194-
Note: if you had installed the gem either using a `git:` or `github:` URL, or had vendored the gem using bundler, you will need to set up your [`.solargraph.yml`](https://solargraph.org/guides/configuration) to include the path to the gem's `lib` directory.
191+
The model classes service as anchor points for both toolchain readable documentation, and language service assisted navigation links. This information also allows the SDK's internals to perform translation between plain and rich data types; e.g., conversion between a `Time` instance and an ISO8601 `String`, and vice versa.
195192

196-
```yaml
197-
include:
198-
- 'vendor/bundle/ruby/*/gems/openai-*/lib/**/*.rb'
199-
```
200-
201-
Otherwise Solargraph will not be able to provide type information or auto-completion for any non-indexed libraries.
202-
203-
### Sorbet
204-
205-
This library is written with [Sorbet type definitions](https://sorbet.org/docs/rbi). However, there is no runtime dependency on the `sorbet-runtime`.
206-
207-
What this means is that while you can use Sorbet to type check your code statically, and benefit from the [Sorbet Language Server](https://sorbet.org/docs/lsp) in your editor, there is no runtime type checking and execution overhead from Sorbet itself.
208-
209-
Due to limitations with the Sorbet type system, where a method otherwise can take an instance of `OpenAI::BaseModel` class, you will need to use the `**` splat operator to pass the arguments:
210-
211-
Please follow Sorbet's [setup guides](https://sorbet.org/docs/adopting) for best experience.
193+
In all places where a `BaseModel` type is specified, vanilla Ruby `Hash` can also be used. For example, the following are interchangeable as arguments:
212194

213195
```ruby
196+
# This has tooling readability, for auto-completion, static analysis, and goto definition with supported language services
214197
params = OpenAI::Models::Chat::CompletionCreateParams.new(
215-
messages: [
216-
OpenAI::Models::ChatCompletionUserMessageParam.new(
217-
role: "user",
218-
content: "Say this is a test"
219-
)
220-
],
221-
model: "gpt-4o"
222-
)
198+
messages: [OpenAI::Models::Chat::ChatCompletionUserMessageParam.new(role: :user, content: "Say this is a test")],
199+
model: :"gpt-4.1"
200+
)
223201

224-
openai.chat.completions.create(**params)
202+
# This also works
203+
params = {
204+
messages: [{role: :user, content: "Say this is a test"}],
205+
model: :"gpt-4.1"
206+
}
225207
```
226208

227-
Note: **This library emits an intentional warning under the [`tapioca` toolchain](https://github.com/Shopify/tapioca)**. This is normal, and does not impact functionality.
228-
229-
### Ruby LSP
230-
231-
The Ruby LSP has [best effort support](https://shopify.github.io/ruby-lsp/#guessed-types) for inferring type information from Ruby code, and as such it may not always be able to provide accurate type information.
232-
233-
## Advanced
234-
235209
### Making custom/undocumented requests
236210

237-
This library is typed for convenient access to the documented API.
238-
239-
If you need to access undocumented endpoints, params, or response properties, the library can still be used.
240-
241211
#### Undocumented request params
242212

243213
If you want to explicitly send an extra param, you can do so with the `extra_query`, `extra_body`, and `extra_headers` under the `request_options:` parameter when making a requests as seen in examples above.
@@ -248,15 +218,15 @@ To make requests to undocumented endpoints, you can make requests using `client.
248218

249219
```ruby
250220
response = client.request(
251-
method: :post,
252-
path: '/undocumented/endpoint',
253-
query: {"dog": "woof"},
254-
headers: {"useful-header": "interesting-value"},
255-
body: {"he": "llo"},
256-
)
221+
method: :post,
222+
path: '/undocumented/endpoint',
223+
query: {"dog": "woof"},
224+
headers: {"useful-header": "interesting-value"},
225+
body: {"he": "llo"},
226+
)
257227
```
258228

259-
### Concurrency & Connection Pooling
229+
### Concurrency & connection pooling
260230

261231
The `OpenAI::Client` instances are thread-safe, and should be re-used across multiple threads. By default, each `Client` have their own HTTP connection pool, with a maximum number of connections equal to thread count.
262232

@@ -266,6 +236,33 @@ Unless otherwise specified, other classes in the SDK do not have locks protectin
266236

267237
Currently, `OpenAI::Client` instances are only fork-safe if there are no in-flight HTTP requests.
268238

239+
### Sorbet
240+
241+
#### Enums
242+
243+
Sorbet's typed enums require sub-classing of the [`T::Enum` class](https://sorbet.org/docs/tenum) from the `sorbet-runtime` gem.
244+
245+
Since this library does not depend on `sorbet-runtime`, it uses a [`T.all` intersection type](https://sorbet.org/docs/intersection-types) with a ruby primitive type to construct a "tagged alias" instead.
246+
247+
```ruby
248+
module OpenAI::Models::ChatModel
249+
# This alias aids language service driven navigation.
250+
TaggedSymbol = T.type_alias { T.all(Symbol, OpenAI::Models::ChatModel) }
251+
end
252+
```
253+
254+
#### Argument passing trick
255+
256+
It is possible to pass a compatible model / parameter class to a method that expects keyword arguments by using the `**` splat operator.
257+
258+
```ruby
259+
params = OpenAI::Models::Chat::CompletionCreateParams.new(
260+
messages: [OpenAI::Models::Chat::ChatCompletionUserMessageParam.new(role: :user, content: "Say this is a test")],
261+
model: :"gpt-4.1"
262+
)
263+
openai.chat.completions.create(**params)
264+
```
265+
269266
## Versioning
270267

271268
This package follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions. As the library is in initial development and has a major version of `0`, APIs may change at any time.
@@ -275,3 +272,7 @@ This package considers improvements to the (non-runtime) `*.rbi` and `*.rbs` typ
275272
## Requirements
276273

277274
Ruby 3.1.0 or higher.
275+
276+
## Contributing
277+
278+
See [the contributing documentation](https://github.com/openai/openai-ruby/tree/main/CONTRIBUTING.md).

Rakefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ end
2121

2222
desc("Preview docs; use `PORT=<PORT>` to change the port")
2323
multitask(:"docs:preview") do
24-
sh(*%w[yard server --bind [::] --reload --quiet --port], ENV.fetch("PORT", "8808"))
24+
sh(*%w[yard server --reload --quiet --bind [::] --port], ENV.fetch("PORT", "8808"))
2525
end
2626

2727
desc("Run test suites; use `TEST=path/to/test.rb` to run a specific test file")
@@ -111,7 +111,7 @@ end
111111
desc("Typecheck everything")
112112
multitask(typecheck: [:"typecheck:steep", :"typecheck:sorbet"])
113113

114-
desc("Lint everything")
114+
desc("Lint and typecheck")
115115
multitask(lint: [:"lint:rubocop", :typecheck])
116116

117117
desc("Build yard docs")

lib/openai.rb

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,6 @@
1919
# We already ship the preferred sorbet manifests in the package itself.
2020
# `tapioca` currently does not offer us a way to opt out of unnecessary compilation.
2121
if Object.const_defined?(:Tapioca) && caller.chain([$PROGRAM_NAME]).chain(ARGV).grep(/tapioca/)
22-
Warning.warn(
23-
<<~WARN
24-
\n
25-
⚠️ skipped loading of "openai" gem under `tapioca`.
26-
27-
This message is normal and expected if you are running a `tapioca` command, and does not impact `.rbi` generation.
28-
\n
29-
WARN
30-
)
3122
return
3223
end
3324

0 commit comments

Comments
 (0)