open_router_enhanced 1.2.5 → 2.0.1
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 +249 -0
- data/Gemfile.lock +28 -23
- data/README.md +83 -0
- data/docs/model_selection.md +30 -0
- data/docs/plugins.md +34 -0
- data/docs/responses_api.md +34 -0
- data/docs/streaming.md +32 -0
- data/docs/structured_outputs.md +31 -0
- data/docs/tools.md +32 -1
- data/lib/open_router/client.rb +183 -80
- data/lib/open_router/completion_options.rb +265 -0
- data/lib/open_router/http.rb +7 -7
- data/lib/open_router/json_healer.rb +7 -0
- data/lib/open_router/model_registry.rb +15 -7
- data/lib/open_router/streaming_client.rb +27 -13
- data/lib/open_router/version.rb +1 -1
- data/lib/open_router.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d443d948a07c5b55d6366e135354b2faa07a8edc38cb2791237a6a4a92bd229a
|
|
4
|
+
data.tar.gz: 37a93b36720b58bf1ee1c4809aa4d54e4d29e06ba27a63c9285a78fa7074eb66
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 78fb6b74df5a7cb901ecac23fe503c667035e4794d6e7d9b97d4ad703e1f0a40347bd3274b86ba13c35501c8afc0b3c29ec5cb7b632eb93013af5a5328403285
|
|
7
|
+
data.tar.gz: 51d704a3035cf8211ac0d9533931d0b1a9bc9ebe49d21f192dd49b7dbb423eadcbf5adcc7b99d3212002947f2646337122e99660a589fa54be22ab3a356555eb
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,254 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [2.0.0] - 2025-12-28
|
|
4
|
+
|
|
5
|
+
### Overview
|
|
6
|
+
|
|
7
|
+
Version 2.0.0 introduces the `CompletionOptions` class - a structured, self-documenting way to configure API requests. This replaces the previous pattern of 11+ keyword arguments with a clean, reusable options object.
|
|
8
|
+
|
|
9
|
+
**This is a semver major release, but existing code will continue to work without modification.** The new patterns are opt-in and recommended for new code.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
### Breaking Changes
|
|
14
|
+
|
|
15
|
+
Method signatures now accept an optional `CompletionOptions` object as the second parameter:
|
|
16
|
+
|
|
17
|
+
| Method | Old Signature | New Signature |
|
|
18
|
+
|--------|---------------|---------------|
|
|
19
|
+
| `complete` | `(messages, model:, tools:, ...)` | `(messages, options = nil, stream:, **kwargs)` |
|
|
20
|
+
| `stream_complete` | `(messages, model:, ...)` | `(messages, options = nil, accumulate_response:, **kwargs, &block)` |
|
|
21
|
+
| `stream` | `(messages, model:, ...)` | `(messages, options = nil, **kwargs, &block)` |
|
|
22
|
+
| `responses` | `(input, model:, ...)` | `(input, options = nil, **kwargs)` |
|
|
23
|
+
|
|
24
|
+
**Important**: The `options` parameter accepts `CompletionOptions`, `Hash`, or `nil`. All existing keyword argument patterns continue to work.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
### Migration Guide
|
|
29
|
+
|
|
30
|
+
#### No Changes Required (Backward Compatible)
|
|
31
|
+
|
|
32
|
+
All existing code continues to work:
|
|
33
|
+
|
|
34
|
+
```ruby
|
|
35
|
+
# ✅ These all work exactly as before:
|
|
36
|
+
client.complete(messages, model: "openai/gpt-4o")
|
|
37
|
+
client.complete(messages, model: "openai/gpt-4o", temperature: 0.7)
|
|
38
|
+
client.stream(messages, model: "openai/gpt-4o") { |chunk| print chunk }
|
|
39
|
+
client.responses("Hello", model: "openai/gpt-4o", reasoning: { effort: "high" })
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
#### Recommended: Use CompletionOptions for New Code
|
|
43
|
+
|
|
44
|
+
For new code, we recommend using `CompletionOptions` for better IDE support, documentation, and reusability:
|
|
45
|
+
|
|
46
|
+
```ruby
|
|
47
|
+
# Create reusable configuration
|
|
48
|
+
opts = OpenRouter::CompletionOptions.new(
|
|
49
|
+
model: "openai/gpt-4o",
|
|
50
|
+
temperature: 0.7,
|
|
51
|
+
max_tokens: 1000
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
# Use across multiple calls
|
|
55
|
+
response1 = client.complete(messages1, opts)
|
|
56
|
+
response2 = client.complete(messages2, opts)
|
|
57
|
+
|
|
58
|
+
# Override specific values without mutating original
|
|
59
|
+
creative_opts = opts.merge(temperature: 1.2)
|
|
60
|
+
response3 = client.complete(messages3, creative_opts)
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
#### Migrating Complex Configurations
|
|
64
|
+
|
|
65
|
+
**Before (v1.x)**:
|
|
66
|
+
```ruby
|
|
67
|
+
client.complete(
|
|
68
|
+
messages,
|
|
69
|
+
model: "openai/gpt-4o",
|
|
70
|
+
tools: my_tools,
|
|
71
|
+
tool_choice: "auto",
|
|
72
|
+
temperature: 0.7,
|
|
73
|
+
max_tokens: 2000,
|
|
74
|
+
providers: ["openai", "azure"],
|
|
75
|
+
response_format: { type: "json_object" },
|
|
76
|
+
extras: { custom_param: "value" }
|
|
77
|
+
)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**After (v2.0 - recommended)**:
|
|
81
|
+
```ruby
|
|
82
|
+
opts = OpenRouter::CompletionOptions.new(
|
|
83
|
+
model: "openai/gpt-4o",
|
|
84
|
+
tools: my_tools,
|
|
85
|
+
tool_choice: "auto",
|
|
86
|
+
temperature: 0.7,
|
|
87
|
+
max_tokens: 2000,
|
|
88
|
+
providers: ["openai", "azure"],
|
|
89
|
+
response_format: { type: "json_object" },
|
|
90
|
+
extras: { custom_param: "value" }
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
client.complete(messages, opts)
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
#### Migrating Streaming Code
|
|
97
|
+
|
|
98
|
+
**Before (v1.x)**:
|
|
99
|
+
```ruby
|
|
100
|
+
client.stream_complete(
|
|
101
|
+
messages,
|
|
102
|
+
model: "openai/gpt-4o",
|
|
103
|
+
accumulate_response: true
|
|
104
|
+
) do |chunk|
|
|
105
|
+
print chunk.dig("choices", 0, "delta", "content")
|
|
106
|
+
end
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
**After (v2.0 - recommended)**:
|
|
110
|
+
```ruby
|
|
111
|
+
opts = OpenRouter::CompletionOptions.new(model: "openai/gpt-4o")
|
|
112
|
+
|
|
113
|
+
client.stream_complete(messages, opts, accumulate_response: true) do |chunk|
|
|
114
|
+
print chunk.dig("choices", 0, "delta", "content")
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Or use the simpler stream method:
|
|
118
|
+
client.stream(messages, opts) { |content| print content }
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
#### Pattern: Base Options with Per-Request Overrides
|
|
122
|
+
|
|
123
|
+
```ruby
|
|
124
|
+
# Define base configuration once
|
|
125
|
+
BASE_OPTS = OpenRouter::CompletionOptions.new(
|
|
126
|
+
model: "openai/gpt-4o",
|
|
127
|
+
max_tokens: 1000,
|
|
128
|
+
providers: ["openai"]
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
# Override for specific use cases
|
|
132
|
+
def generate_creative_content(prompt)
|
|
133
|
+
messages = [{ role: "user", content: prompt }]
|
|
134
|
+
client.complete(messages, BASE_OPTS, temperature: 1.2)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def generate_factual_content(prompt)
|
|
138
|
+
messages = [{ role: "user", content: prompt }]
|
|
139
|
+
client.complete(messages, BASE_OPTS, temperature: 0.1)
|
|
140
|
+
end
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
### Added
|
|
146
|
+
|
|
147
|
+
#### `OpenRouter::CompletionOptions` Class
|
|
148
|
+
|
|
149
|
+
A structured configuration object supporting **30+ parameters** organized by category:
|
|
150
|
+
|
|
151
|
+
**Core Parameters**:
|
|
152
|
+
- `model` - Model ID string or array for fallback routing
|
|
153
|
+
- `tools` - Tool/function definitions
|
|
154
|
+
- `tool_choice` - `"auto"`, `"none"`, `"required"`, or specific tool
|
|
155
|
+
- `extras` - Hash for pass-through of any additional/future parameters
|
|
156
|
+
|
|
157
|
+
**Sampling Parameters** (control response randomness):
|
|
158
|
+
- `temperature` - 0.0-2.0, controls randomness (default varies by model)
|
|
159
|
+
- `top_p` - 0.0-1.0, nucleus sampling threshold
|
|
160
|
+
- `top_k` - Integer, limits token selection to top K
|
|
161
|
+
- `frequency_penalty` - -2.0 to 2.0, penalize frequent tokens
|
|
162
|
+
- `presence_penalty` - -2.0 to 2.0, penalize tokens already present
|
|
163
|
+
- `repetition_penalty` - 0.0-2.0, general repetition penalty
|
|
164
|
+
- `min_p` - 0.0-1.0, minimum probability threshold
|
|
165
|
+
- `top_a` - 0.0-1.0, dynamic token filtering
|
|
166
|
+
- `seed` - Integer for reproducible outputs
|
|
167
|
+
|
|
168
|
+
**Output Control**:
|
|
169
|
+
- `max_tokens` - Maximum tokens to generate (legacy)
|
|
170
|
+
- `max_completion_tokens` - Maximum tokens (preferred, newer API)
|
|
171
|
+
- `stop` - String or array of stop sequences
|
|
172
|
+
- `logprobs` - Boolean, return log probabilities
|
|
173
|
+
- `top_logprobs` - 0-20, number of top logprobs per token
|
|
174
|
+
- `logit_bias` - Hash mapping token IDs to bias values (-100 to 100)
|
|
175
|
+
- `response_format` - Structured output schema configuration
|
|
176
|
+
- `parallel_tool_calls` - Boolean, allow parallel function calls
|
|
177
|
+
- `verbosity` - `:low`, `:medium`, `:high`
|
|
178
|
+
|
|
179
|
+
**OpenRouter Routing**:
|
|
180
|
+
- `providers` - Array of provider names (becomes `provider.order`)
|
|
181
|
+
- `provider` - Full provider config hash (overrides `providers`)
|
|
182
|
+
- `transforms` - Array of transform identifiers
|
|
183
|
+
- `plugins` - Array of plugin configs (`web-search`, `response-healing`, etc.)
|
|
184
|
+
- `prediction` - Predicted output for latency optimization
|
|
185
|
+
- `route` - `"fallback"` or `"sort"`
|
|
186
|
+
- `metadata` - Custom key-value metadata
|
|
187
|
+
- `user` - End-user identifier for tracking
|
|
188
|
+
- `session_id` - Session grouping identifier (max 128 chars)
|
|
189
|
+
|
|
190
|
+
**Responses API**:
|
|
191
|
+
- `reasoning` - Hash with `effort:` key (`"minimal"`, `"low"`, `"medium"`, `"high"`)
|
|
192
|
+
|
|
193
|
+
**Client-Side Options** (not sent to API):
|
|
194
|
+
- `force_structured_output` - Override forced extraction mode behavior
|
|
195
|
+
|
|
196
|
+
#### Helper Methods
|
|
197
|
+
|
|
198
|
+
```ruby
|
|
199
|
+
opts = CompletionOptions.new(model: "gpt-4", tools: [...])
|
|
200
|
+
|
|
201
|
+
opts.has_tools? # => true if tools are defined
|
|
202
|
+
opts.has_response_format? # => true if response_format is set
|
|
203
|
+
opts.fallback_models? # => true if model is an array
|
|
204
|
+
|
|
205
|
+
opts.to_h # => Hash of all non-nil, non-empty values
|
|
206
|
+
opts.to_api_params # => Hash for API request (excludes client-side params)
|
|
207
|
+
opts.merge(temp: 0.5) # => New CompletionOptions with override
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
### Backward Compatibility
|
|
213
|
+
|
|
214
|
+
**All existing patterns continue to work**:
|
|
215
|
+
|
|
216
|
+
```ruby
|
|
217
|
+
# Direct kwargs (unchanged from v1.x)
|
|
218
|
+
client.complete(messages, model: "gpt-4")
|
|
219
|
+
|
|
220
|
+
# Hash as second argument
|
|
221
|
+
client.complete(messages, { model: "gpt-4", temperature: 0.7 })
|
|
222
|
+
|
|
223
|
+
# CompletionOptions object (new in v2.0)
|
|
224
|
+
opts = CompletionOptions.new(model: "gpt-4")
|
|
225
|
+
client.complete(messages, opts)
|
|
226
|
+
|
|
227
|
+
# Options with kwargs overrides (new in v2.0)
|
|
228
|
+
client.complete(messages, opts, temperature: 0.9)
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
The `normalize_options` helper transparently handles all input styles.
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
### Internal Improvements
|
|
236
|
+
|
|
237
|
+
- New `normalize_options` private helper for flexible input handling
|
|
238
|
+
- Refactored `prepare_base_parameters` to accept `CompletionOptions`
|
|
239
|
+
- Refactored `configure_tools_and_structured_outputs!` to use `CompletionOptions`
|
|
240
|
+
- Added focused parameter helpers:
|
|
241
|
+
- `configure_sampling_parameters!`
|
|
242
|
+
- `configure_output_parameters!`
|
|
243
|
+
- `configure_routing_parameters!`
|
|
244
|
+
- Improved separation of concerns in request building
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
### Bug Fixes
|
|
249
|
+
|
|
250
|
+
- Fixed issue where `extras` hash contents were nested incorrectly in API requests. Parameters like `max_tokens` passed via `extras` now correctly appear at the top level of the request body.
|
|
251
|
+
|
|
3
252
|
## [1.2.2] - 2025-12-25
|
|
4
253
|
|
|
5
254
|
### Fixed
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
open_router_enhanced (
|
|
4
|
+
open_router_enhanced (2.0.0)
|
|
5
5
|
activesupport (>= 6.0, < 9.0)
|
|
6
6
|
dotenv (>= 2.0, < 4.0)
|
|
7
7
|
faraday (>= 1.0, < 3.0)
|
|
@@ -11,7 +11,7 @@ PATH
|
|
|
11
11
|
GEM
|
|
12
12
|
remote: https://rubygems.org/
|
|
13
13
|
specs:
|
|
14
|
-
activesupport (8.1.
|
|
14
|
+
activesupport (8.1.3)
|
|
15
15
|
base64
|
|
16
16
|
bigdecimal
|
|
17
17
|
concurrent-ruby (~> 1.0, >= 1.3.1)
|
|
@@ -24,11 +24,11 @@ GEM
|
|
|
24
24
|
securerandom (>= 0.3)
|
|
25
25
|
tzinfo (~> 2.0, >= 2.0.5)
|
|
26
26
|
uri (>= 0.13.1)
|
|
27
|
-
addressable (2.
|
|
27
|
+
addressable (2.9.0)
|
|
28
28
|
public_suffix (>= 2.0.2, < 8.0)
|
|
29
29
|
ast (2.4.3)
|
|
30
30
|
base64 (0.3.0)
|
|
31
|
-
bigdecimal (4.
|
|
31
|
+
bigdecimal (4.1.1)
|
|
32
32
|
coderay (1.1.3)
|
|
33
33
|
concurrent-ruby (1.3.6)
|
|
34
34
|
connection_pool (3.0.2)
|
|
@@ -38,42 +38,47 @@ GEM
|
|
|
38
38
|
diff-lcs (1.6.2)
|
|
39
39
|
dotenv (3.2.0)
|
|
40
40
|
drb (2.2.3)
|
|
41
|
-
faraday (2.14.
|
|
41
|
+
faraday (2.14.1)
|
|
42
42
|
faraday-net_http (>= 2.0, < 3.5)
|
|
43
43
|
json
|
|
44
44
|
logger
|
|
45
|
-
faraday-multipart (1.
|
|
45
|
+
faraday-multipart (1.2.0)
|
|
46
46
|
multipart-post (~> 2.0)
|
|
47
47
|
faraday-net_http (3.4.2)
|
|
48
48
|
net-http (~> 0.5)
|
|
49
49
|
hashdiff (1.2.1)
|
|
50
50
|
i18n (1.14.8)
|
|
51
51
|
concurrent-ruby (~> 1.0)
|
|
52
|
-
|
|
52
|
+
io-console (0.8.2)
|
|
53
|
+
json (2.19.3)
|
|
53
54
|
json-schema (4.3.1)
|
|
54
55
|
addressable (>= 2.8)
|
|
55
56
|
language_server-protocol (3.17.0.5)
|
|
56
57
|
lint_roller (1.1.0)
|
|
57
58
|
logger (1.7.0)
|
|
58
59
|
method_source (1.1.0)
|
|
59
|
-
minitest (6.0.
|
|
60
|
+
minitest (6.0.4)
|
|
61
|
+
drb (~> 2.0)
|
|
60
62
|
prism (~> 1.5)
|
|
61
63
|
multipart-post (2.4.1)
|
|
62
64
|
net-http (0.9.1)
|
|
63
65
|
uri (>= 0.11.1)
|
|
64
|
-
parallel (
|
|
65
|
-
parser (3.3.
|
|
66
|
+
parallel (2.0.1)
|
|
67
|
+
parser (3.3.11.1)
|
|
66
68
|
ast (~> 2.4.1)
|
|
67
69
|
racc
|
|
68
|
-
prism (1.
|
|
69
|
-
pry (0.
|
|
70
|
+
prism (1.9.0)
|
|
71
|
+
pry (0.16.0)
|
|
70
72
|
coderay (~> 1.1)
|
|
71
73
|
method_source (~> 1.0)
|
|
72
|
-
|
|
74
|
+
reline (>= 0.6.0)
|
|
75
|
+
public_suffix (7.0.5)
|
|
73
76
|
racc (1.8.1)
|
|
74
77
|
rainbow (3.1.1)
|
|
75
|
-
rake (13.
|
|
76
|
-
regexp_parser (2.
|
|
78
|
+
rake (13.4.2)
|
|
79
|
+
regexp_parser (2.12.0)
|
|
80
|
+
reline (0.6.3)
|
|
81
|
+
io-console (~> 0.5)
|
|
77
82
|
rexml (3.4.4)
|
|
78
83
|
rspec (3.13.2)
|
|
79
84
|
rspec-core (~> 3.13.0)
|
|
@@ -84,24 +89,24 @@ GEM
|
|
|
84
89
|
rspec-expectations (3.13.5)
|
|
85
90
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
86
91
|
rspec-support (~> 3.13.0)
|
|
87
|
-
rspec-mocks (3.13.
|
|
92
|
+
rspec-mocks (3.13.8)
|
|
88
93
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
89
94
|
rspec-support (~> 3.13.0)
|
|
90
|
-
rspec-support (3.13.
|
|
91
|
-
rubocop (1.
|
|
95
|
+
rspec-support (3.13.7)
|
|
96
|
+
rubocop (1.86.1)
|
|
92
97
|
json (~> 2.3)
|
|
93
98
|
language_server-protocol (~> 3.17.0.2)
|
|
94
99
|
lint_roller (~> 1.1.0)
|
|
95
|
-
parallel (
|
|
100
|
+
parallel (>= 1.10)
|
|
96
101
|
parser (>= 3.3.0.2)
|
|
97
102
|
rainbow (>= 2.2.2, < 4.0)
|
|
98
103
|
regexp_parser (>= 2.9.3, < 3.0)
|
|
99
|
-
rubocop-ast (>= 1.
|
|
104
|
+
rubocop-ast (>= 1.49.0, < 2.0)
|
|
100
105
|
ruby-progressbar (~> 1.7)
|
|
101
106
|
unicode-display_width (>= 2.4.0, < 4.0)
|
|
102
|
-
rubocop-ast (1.
|
|
107
|
+
rubocop-ast (1.49.1)
|
|
103
108
|
parser (>= 3.3.7.2)
|
|
104
|
-
prism (~> 1.
|
|
109
|
+
prism (~> 1.7)
|
|
105
110
|
ruby-progressbar (1.13.0)
|
|
106
111
|
securerandom (0.4.1)
|
|
107
112
|
tzinfo (2.0.6)
|
|
@@ -111,7 +116,7 @@ GEM
|
|
|
111
116
|
unicode-emoji (4.2.0)
|
|
112
117
|
uri (1.1.1)
|
|
113
118
|
vcr (6.4.0)
|
|
114
|
-
webmock (3.26.
|
|
119
|
+
webmock (3.26.2)
|
|
115
120
|
addressable (>= 2.8.0)
|
|
116
121
|
crack (>= 0.3.2)
|
|
117
122
|
hashdiff (>= 0.4.0, < 2.0.0)
|
data/README.md
CHANGED
|
@@ -198,6 +198,89 @@ end
|
|
|
198
198
|
|
|
199
199
|
**[Full configuration documentation](docs/configuration.md)**
|
|
200
200
|
|
|
201
|
+
## CompletionOptions
|
|
202
|
+
|
|
203
|
+
For complex requests with many parameters, use `CompletionOptions` to organize your configuration:
|
|
204
|
+
|
|
205
|
+
```ruby
|
|
206
|
+
# Create reusable options
|
|
207
|
+
opts = OpenRouter::CompletionOptions.new(
|
|
208
|
+
model: "anthropic/claude-3.5-sonnet",
|
|
209
|
+
temperature: 0.7,
|
|
210
|
+
max_tokens: 1000,
|
|
211
|
+
tools: [weather_tool],
|
|
212
|
+
providers: ["anthropic"]
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
# Use with complete()
|
|
216
|
+
response = client.complete(messages, opts)
|
|
217
|
+
|
|
218
|
+
# Override specific values
|
|
219
|
+
response = client.complete(messages, opts, temperature: 0.9)
|
|
220
|
+
|
|
221
|
+
# All these styles work (backward compatible):
|
|
222
|
+
client.complete(messages, model: "gpt-4") # kwargs
|
|
223
|
+
client.complete(messages, { model: "gpt-4" }) # hash
|
|
224
|
+
client.complete(messages, opts) # options object
|
|
225
|
+
client.complete(messages, opts, temperature: 0.5) # options + override
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Available Parameters
|
|
229
|
+
|
|
230
|
+
```ruby
|
|
231
|
+
OpenRouter::CompletionOptions.new(
|
|
232
|
+
# Model selection
|
|
233
|
+
model: "gpt-4", # Model ID or array for fallback
|
|
234
|
+
route: "fallback", # Routing strategy
|
|
235
|
+
|
|
236
|
+
# Sampling parameters
|
|
237
|
+
temperature: 0.7, # 0.0-2.0
|
|
238
|
+
top_p: 0.9, # Nucleus sampling
|
|
239
|
+
top_k: 50, # Top-K sampling
|
|
240
|
+
frequency_penalty: 0.5, # -2.0 to 2.0
|
|
241
|
+
presence_penalty: 0.3, # -2.0 to 2.0
|
|
242
|
+
repetition_penalty: 1.1, # 0.0-2.0
|
|
243
|
+
min_p: 0.05, # Minimum probability
|
|
244
|
+
top_a: 0.1, # Dynamic filtering
|
|
245
|
+
seed: 42, # Reproducibility
|
|
246
|
+
|
|
247
|
+
# Output control
|
|
248
|
+
max_tokens: 1000, # Max completion tokens
|
|
249
|
+
max_completion_tokens: 1000, # Preferred over max_tokens
|
|
250
|
+
stop: ["\n", "END"], # Stop sequences
|
|
251
|
+
logprobs: true, # Return log probabilities
|
|
252
|
+
top_logprobs: 5, # Number of top logprobs
|
|
253
|
+
logit_bias: { "50256" => -100 }, # Token biasing
|
|
254
|
+
response_format: schema, # Structured output
|
|
255
|
+
parallel_tool_calls: true, # Allow parallel calls
|
|
256
|
+
|
|
257
|
+
# Tools
|
|
258
|
+
tools: [weather_tool], # Tool definitions
|
|
259
|
+
tool_choice: "auto", # auto, none, required, or specific
|
|
260
|
+
|
|
261
|
+
# OpenRouter routing
|
|
262
|
+
providers: ["anthropic", "openai"], # Simple provider ordering
|
|
263
|
+
provider: { # Full provider config
|
|
264
|
+
order: ["anthropic"],
|
|
265
|
+
quantizations: ["fp16"],
|
|
266
|
+
allow_fallbacks: true
|
|
267
|
+
},
|
|
268
|
+
transforms: ["middle-out"], # Message transforms
|
|
269
|
+
plugins: [{ id: "web-search" }], # OpenRouter plugins
|
|
270
|
+
prediction: { type: "content", content: "..." }, # Latency optimization
|
|
271
|
+
metadata: { request_id: "abc123" }, # Custom metadata
|
|
272
|
+
user: "user_123", # User identifier
|
|
273
|
+
session_id: "session_456", # Session grouping
|
|
274
|
+
|
|
275
|
+
# Responses API
|
|
276
|
+
reasoning: { effort: "high" }, # For reasoning models
|
|
277
|
+
|
|
278
|
+
# Client-side
|
|
279
|
+
force_structured_output: true, # Force schema injection
|
|
280
|
+
extras: { custom_param: "value" } # Pass-through params
|
|
281
|
+
)
|
|
282
|
+
```
|
|
283
|
+
|
|
201
284
|
## Features
|
|
202
285
|
|
|
203
286
|
### Tool Calling
|
data/docs/model_selection.md
CHANGED
|
@@ -15,6 +15,36 @@ model = OpenRouter::ModelSelector.new
|
|
|
15
15
|
response = client.complete(messages, model: model, tools: tools)
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
+
## Using CompletionOptions with Model Selection (v2.0+)
|
|
19
|
+
|
|
20
|
+
Combine model selection with `CompletionOptions` for powerful, reusable configurations:
|
|
21
|
+
|
|
22
|
+
```ruby
|
|
23
|
+
# Select model dynamically
|
|
24
|
+
model = OpenRouter::ModelSelector.new
|
|
25
|
+
.require(:function_calling, :structured_outputs)
|
|
26
|
+
.optimize_for(:cost)
|
|
27
|
+
.choose
|
|
28
|
+
|
|
29
|
+
# Create reusable options with the selected model
|
|
30
|
+
opts = OpenRouter::CompletionOptions.new(
|
|
31
|
+
model: model,
|
|
32
|
+
tools: my_tools,
|
|
33
|
+
max_tokens: 1000
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
# Use across multiple calls
|
|
37
|
+
response = client.complete(messages, opts)
|
|
38
|
+
|
|
39
|
+
# Or use fallback model arrays directly in options
|
|
40
|
+
fallback_opts = OpenRouter::CompletionOptions.new(
|
|
41
|
+
model: ["anthropic/claude-3.5-sonnet", "openai/gpt-4o", "google/gemini-pro"],
|
|
42
|
+
route: "fallback"
|
|
43
|
+
)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
All keyword argument patterns continue to work for backward compatibility.
|
|
47
|
+
|
|
18
48
|
## ModelSelector API
|
|
19
49
|
|
|
20
50
|
The `ModelSelector` class provides a fluent interface for building complex model selection criteria.
|
data/docs/plugins.md
CHANGED
|
@@ -31,6 +31,40 @@ response = client.complete(
|
|
|
31
31
|
)
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
+
## Using CompletionOptions with Plugins (v2.0+)
|
|
35
|
+
|
|
36
|
+
For cleaner, reusable configurations, use the `CompletionOptions` class:
|
|
37
|
+
|
|
38
|
+
```ruby
|
|
39
|
+
# Create reusable plugin configuration
|
|
40
|
+
web_search_opts = OpenRouter::CompletionOptions.new(
|
|
41
|
+
model: "openai/gpt-4o-mini",
|
|
42
|
+
plugins: [{ id: "web-search" }]
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
# Use across multiple calls
|
|
46
|
+
response = client.complete(messages, web_search_opts)
|
|
47
|
+
|
|
48
|
+
# Combine multiple plugins with other options
|
|
49
|
+
research_opts = OpenRouter::CompletionOptions.new(
|
|
50
|
+
model: "openai/gpt-4o",
|
|
51
|
+
plugins: [
|
|
52
|
+
{ id: "web-search" },
|
|
53
|
+
{ id: "pdf-inputs" }
|
|
54
|
+
],
|
|
55
|
+
max_tokens: 2000,
|
|
56
|
+
temperature: 0.3
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
# Add prediction for latency optimization
|
|
60
|
+
fast_opts = OpenRouter::CompletionOptions.new(
|
|
61
|
+
model: "openai/gpt-4o",
|
|
62
|
+
prediction: { type: "content", content: "The answer is..." }
|
|
63
|
+
)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
All keyword argument patterns continue to work for backward compatibility.
|
|
67
|
+
|
|
34
68
|
## Response Healing Plugin
|
|
35
69
|
|
|
36
70
|
The response-healing plugin fixes common JSON formatting issues server-side:
|
data/docs/responses_api.md
CHANGED
|
@@ -17,6 +17,40 @@ response = client.responses(
|
|
|
17
17
|
puts response.content # => "Paris"
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
+
## Using CompletionOptions (v2.0+)
|
|
21
|
+
|
|
22
|
+
For cleaner, reusable configurations, use the `CompletionOptions` class:
|
|
23
|
+
|
|
24
|
+
```ruby
|
|
25
|
+
# Create reusable reasoning configuration
|
|
26
|
+
reasoning_opts = OpenRouter::CompletionOptions.new(
|
|
27
|
+
model: "openai/o4-mini",
|
|
28
|
+
reasoning: { effort: "high" },
|
|
29
|
+
max_tokens: 1000
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
# Use with responses
|
|
33
|
+
response = client.responses("Explain quantum entanglement", reasoning_opts)
|
|
34
|
+
|
|
35
|
+
# Override specific values per-request
|
|
36
|
+
response = client.responses(
|
|
37
|
+
"What is 15% of 80?",
|
|
38
|
+
reasoning_opts,
|
|
39
|
+
reasoning: { effort: "low" } # Simpler problem, less reasoning needed
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
# Create tool-enabled responses configuration
|
|
43
|
+
tool_opts = OpenRouter::CompletionOptions.new(
|
|
44
|
+
model: "openai/gpt-4o-mini",
|
|
45
|
+
tools: [weather_tool, calculator_tool],
|
|
46
|
+
tool_choice: "auto"
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
response = client.responses("What's the weather in Tokyo?", tool_opts)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
All keyword argument patterns continue to work for backward compatibility.
|
|
53
|
+
|
|
20
54
|
## With Reasoning
|
|
21
55
|
|
|
22
56
|
The Responses API supports reasoning with configurable effort levels:
|
data/docs/streaming.md
CHANGED
|
@@ -22,6 +22,38 @@ response = streaming_client.stream_complete(
|
|
|
22
22
|
puts response.content # Complete response after streaming
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
+
## Using CompletionOptions (v2.0+)
|
|
26
|
+
|
|
27
|
+
For cleaner, reusable configurations, use the `CompletionOptions` class:
|
|
28
|
+
|
|
29
|
+
```ruby
|
|
30
|
+
# Create reusable streaming configuration
|
|
31
|
+
stream_opts = OpenRouter::CompletionOptions.new(
|
|
32
|
+
model: "openai/gpt-4o-mini",
|
|
33
|
+
temperature: 0.8,
|
|
34
|
+
max_tokens: 2000
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
# Use with stream_complete
|
|
38
|
+
response = streaming_client.stream_complete(
|
|
39
|
+
messages,
|
|
40
|
+
stream_opts,
|
|
41
|
+
accumulate_response: true
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
# Use with simple stream method
|
|
45
|
+
streaming_client.stream(messages, stream_opts) do |chunk|
|
|
46
|
+
print chunk
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Override specific values per-request
|
|
50
|
+
streaming_client.stream(messages, stream_opts, temperature: 0.2) do |chunk|
|
|
51
|
+
print chunk
|
|
52
|
+
end
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
All keyword argument patterns continue to work for backward compatibility.
|
|
56
|
+
|
|
25
57
|
## Streaming with Callbacks
|
|
26
58
|
|
|
27
59
|
The streaming client supports extensive callback events for monitoring and custom processing.
|
data/docs/structured_outputs.md
CHANGED
|
@@ -35,6 +35,37 @@ puts user["age"] # => 30
|
|
|
35
35
|
puts user["email"] # => "john@example.com"
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
+
## Using CompletionOptions (v2.0+)
|
|
39
|
+
|
|
40
|
+
For cleaner, reusable configurations, use the `CompletionOptions` class:
|
|
41
|
+
|
|
42
|
+
```ruby
|
|
43
|
+
# Create reusable structured output configuration
|
|
44
|
+
struct_opts = OpenRouter::CompletionOptions.new(
|
|
45
|
+
model: "openai/gpt-4o",
|
|
46
|
+
response_format: user_schema,
|
|
47
|
+
max_tokens: 500,
|
|
48
|
+
temperature: 0.1 # Lower temperature for more deterministic outputs
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
# Use across multiple calls
|
|
52
|
+
response1 = client.complete(messages1, struct_opts)
|
|
53
|
+
response2 = client.complete(messages2, struct_opts)
|
|
54
|
+
|
|
55
|
+
# Override for specific requests
|
|
56
|
+
creative_opts = struct_opts.merge(temperature: 0.8)
|
|
57
|
+
response3 = client.complete(messages3, creative_opts)
|
|
58
|
+
|
|
59
|
+
# Control forced structured output behavior
|
|
60
|
+
opts_with_force = OpenRouter::CompletionOptions.new(
|
|
61
|
+
model: "some-model",
|
|
62
|
+
response_format: schema,
|
|
63
|
+
force_structured_output: true # Override auto-detection
|
|
64
|
+
)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
All keyword argument patterns continue to work for backward compatibility.
|
|
68
|
+
|
|
38
69
|
## Key Concepts: JSON Content vs Structured Outputs
|
|
39
70
|
|
|
40
71
|
**Important: These are fundamentally different features.**
|