spectre_ai 2.1.0 → 2.1.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 +87 -0
- data/README.md +72 -0
- data/lib/spectre/claude/completions.rb +10 -2
- data/lib/spectre/gemini/completions.rb +10 -2
- data/lib/spectre/ollama/completions.rb +11 -5
- data/lib/spectre/openai/completions.rb +10 -2
- data/lib/spectre/openrouter/completions.rb +8 -2
- data/lib/spectre/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 83d3a297e011e019679dcb12edb0c00f3bb73c6dc599378923627ef257ff6f1f
|
|
4
|
+
data.tar.gz: 79def4a06049ed718bf0c66ffc7f0a29016d8a0831ab0941cc9c02f0b451ab03
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 18cea546ff80840b1cb6087b35305a6efdf17fd8c6b6bea565157336958b02105822bb5725d7bb8e23a170362105506143992feb52ba6834986ced9fe87ab21d
|
|
7
|
+
data.tar.gz: 2397f388fbab927a41b959c92364f2cbbc50e8d6cebe1ed4a0ea33b631fa0d2e635687d349f523d5f20d88f414d176f9b297163337ed3632232cb520f04040f9
|
data/CHANGELOG.md
CHANGED
|
@@ -308,8 +308,94 @@ Key Benefits:\
|
|
|
308
308
|
- Added RSpec tests for `Spectre::Openrouter::Completions` and `Spectre::Openrouter::Embeddings` covering:
|
|
309
309
|
- Success responses, error propagation, JSON parse errors.
|
|
310
310
|
- Finish reasons and refusal handling.
|
|
311
|
+
|
|
312
|
+
# Changelog for Version 2.1.1
|
|
313
|
+
|
|
314
|
+
**Release Date:** [15th Dec 2025]
|
|
315
|
+
|
|
316
|
+
### Enhancements: Extra generation options for Completions
|
|
317
|
+
|
|
318
|
+
- You can now pass additional generation options (e.g., `temperature`, `top_p`, `presence_penalty`) directly as keyword arguments to all `Completions.create` methods.
|
|
319
|
+
- For OpenAI, OpenRouter, Gemini, and Claude these extra kwargs are forwarded into the request body automatically.
|
|
320
|
+
- For Ollama, pass extra kwargs at the top level just like other providers. Spectre maps them into `body[:options]` internally (including `max_tokens`). The legacy `ollama: { options: ... }` is now ignored.
|
|
321
|
+
|
|
322
|
+
### Notes and exclusions
|
|
323
|
+
|
|
324
|
+
- Control/network keys are not forwarded: `read_timeout`, `open_timeout`.
|
|
325
|
+
- `max_tokens` remains supported:
|
|
326
|
+
- OpenAI/OpenRouter/Gemini/Claude: stays a top‑level request body field.
|
|
327
|
+
- Ollama: forwarded into `:options` along with other generation kwargs.
|
|
328
|
+
- Claude: `tool_choice` is NOT auto‑forwarded from extra kwargs; pass it explicitly via the dedicated parameter if needed.
|
|
329
|
+
|
|
330
|
+
### Examples
|
|
331
|
+
|
|
332
|
+
```ruby
|
|
333
|
+
# OpenAI
|
|
334
|
+
Spectre::Openai::Completions.create(
|
|
335
|
+
messages: [ { role: 'user', content: 'Hi' } ],
|
|
336
|
+
model: 'gpt-4o-mini',
|
|
337
|
+
temperature: 0.1,
|
|
338
|
+
top_p: 0.9,
|
|
339
|
+
max_tokens: 512
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
# OpenRouter
|
|
343
|
+
Spectre::Openrouter::Completions.create(
|
|
344
|
+
messages: [ { role: 'user', content: 'Hi' } ],
|
|
345
|
+
model: 'openai/gpt-4o-mini',
|
|
346
|
+
temperature: 0.1,
|
|
347
|
+
presence_penalty: 0.2,
|
|
348
|
+
max_tokens: 256
|
|
349
|
+
)
|
|
350
|
+
|
|
351
|
+
# Gemini (OpenAI‑compatible endpoint)
|
|
352
|
+
Spectre::Gemini::Completions.create(
|
|
353
|
+
messages: [ { role: 'user', content: 'Hi' } ],
|
|
354
|
+
model: 'gemini-2.5-flash',
|
|
355
|
+
temperature: 0.1,
|
|
356
|
+
max_tokens: 256
|
|
357
|
+
)
|
|
358
|
+
|
|
359
|
+
# Claude
|
|
360
|
+
Spectre::Claude::Completions.create(
|
|
361
|
+
messages: [ { role: 'user', content: 'Hi' } ],
|
|
362
|
+
model: 'claude-opus-4-1',
|
|
363
|
+
temperature: 0.1,
|
|
364
|
+
max_tokens: 512,
|
|
365
|
+
tool_choice: { type: 'auto' } # pass explicitly when needed
|
|
366
|
+
)
|
|
367
|
+
|
|
368
|
+
# Ollama — pass options at top level; Spectre maps them to body[:options]
|
|
369
|
+
Spectre::Ollama::Completions.create(
|
|
370
|
+
messages: [ { role: 'user', content: 'Hi' } ],
|
|
371
|
+
model: 'llama3.1:8b',
|
|
372
|
+
temperature: 0.1,
|
|
373
|
+
max_tokens: 256, # forwarded into body[:options]
|
|
374
|
+
path: 'api/chat' # optional: override endpoint path
|
|
375
|
+
)
|
|
376
|
+
## Note: `ollama: { options: ... }` is ignored; use top-level kwargs instead.
|
|
377
|
+
```
|
|
311
378
|
- Request body formation (max_tokens, tools, response_format.json_schema).
|
|
312
379
|
|
|
380
|
+
### OpenRouter: Plugins support in chat completions
|
|
381
|
+
|
|
382
|
+
- Added pass-through support for OpenRouter Plugins in chat completions.
|
|
383
|
+
- You can pass the `plugins` array directly to `Spectre::Openrouter::Completions.create`, and it will be included in the request body.
|
|
384
|
+
|
|
385
|
+
Example:
|
|
386
|
+
|
|
387
|
+
```ruby
|
|
388
|
+
Spectre::Openrouter::Completions.create(
|
|
389
|
+
messages: [ { role: 'user', content: 'Heal my response if needed' } ],
|
|
390
|
+
model: 'openai/gpt-4o-mini',
|
|
391
|
+
plugins: [ { id: 'response-healing' } ],
|
|
392
|
+
temperature: 0.2,
|
|
393
|
+
max_tokens: 256
|
|
394
|
+
)
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
Docs: https://openrouter.ai/docs/guides/features/plugins/overview
|
|
398
|
+
|
|
313
399
|
### Breaking Changes
|
|
314
400
|
|
|
315
401
|
- Unified `max_tokens` option across providers:
|
|
@@ -336,3 +422,4 @@ Key Benefits:\
|
|
|
336
422
|
```ruby
|
|
337
423
|
Spectre::Openrouter::Embeddings.create('some text', model: 'text-embedding-3-small')
|
|
338
424
|
```
|
|
425
|
+
|
data/README.md
CHANGED
|
@@ -224,6 +224,78 @@ Spectre.provider_module::Completions.create(
|
|
|
224
224
|
|
|
225
225
|
```
|
|
226
226
|
|
|
227
|
+
#### Passing extra generation options (temperature, top_p, etc.)
|
|
228
|
+
|
|
229
|
+
You can pass common generation options directly as keyword arguments to `Completions.create`.
|
|
230
|
+
|
|
231
|
+
- OpenAI/OpenRouter/Gemini/Claude: extra kwargs are forwarded into the request body (e.g., `temperature`, `top_p`, `presence_penalty`).
|
|
232
|
+
- Ollama: pass extra kwargs the same way (top-level). Spectre will put them into `body[:options]` internally (including `max_tokens`). The `ollama: { options: ... }` hash is no longer used.
|
|
233
|
+
- Excluded control keys: `read_timeout`, `open_timeout` are never forwarded.
|
|
234
|
+
- Provider differences for `max_tokens`:
|
|
235
|
+
- OpenAI/OpenRouter/Gemini/Claude: `max_tokens` is a top‑level field in the request body.
|
|
236
|
+
- Ollama: `max_tokens` is forwarded into `body[:options]`.
|
|
237
|
+
- Claude: `tool_choice` is not auto‑forwarded; provide it explicitly via the `tool_choice:` parameter when needed.
|
|
238
|
+
|
|
239
|
+
Examples:
|
|
240
|
+
|
|
241
|
+
```ruby
|
|
242
|
+
# OpenAI
|
|
243
|
+
Spectre::Openai::Completions.create(
|
|
244
|
+
messages: [ { role: 'user', content: 'Hi' } ],
|
|
245
|
+
model: 'gpt-4o-mini',
|
|
246
|
+
temperature: 0.1,
|
|
247
|
+
top_p: 0.9,
|
|
248
|
+
max_tokens: 512
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
# OpenRouter
|
|
252
|
+
Spectre::Openrouter::Completions.create(
|
|
253
|
+
messages: [ { role: 'user', content: 'Hi' } ],
|
|
254
|
+
model: 'openai/gpt-4o-mini',
|
|
255
|
+
temperature: 0.1,
|
|
256
|
+
presence_penalty: 0.2,
|
|
257
|
+
max_tokens: 256
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
# OpenRouter with Plugins
|
|
261
|
+
# Docs: https://openrouter.ai/docs/guides/features/plugins/overview
|
|
262
|
+
Spectre::Openrouter::Completions.create(
|
|
263
|
+
messages: [ { role: 'user', content: 'Heal my response if needed' } ],
|
|
264
|
+
model: 'openai/gpt-4o-mini',
|
|
265
|
+
plugins: [ { id: 'response-healing' } ],
|
|
266
|
+
temperature: 0.2,
|
|
267
|
+
max_tokens: 256
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
# Gemini (OpenAI‑compatible endpoint)
|
|
271
|
+
Spectre::Gemini::Completions.create(
|
|
272
|
+
messages: [ { role: 'user', content: 'Hi' } ],
|
|
273
|
+
model: 'gemini-2.5-flash',
|
|
274
|
+
temperature: 0.1,
|
|
275
|
+
max_tokens: 256
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
# Claude
|
|
279
|
+
Spectre::Claude::Completions.create(
|
|
280
|
+
messages: [ { role: 'user', content: 'Hi' } ],
|
|
281
|
+
model: 'claude-opus-4-1',
|
|
282
|
+
temperature: 0.1,
|
|
283
|
+
max_tokens: 512,
|
|
284
|
+
tool_choice: { type: 'auto' } # pass explicitly when needed
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
# Ollama — pass options at top level (Spectre maps them to body[:options])
|
|
288
|
+
Spectre::Ollama::Completions.create(
|
|
289
|
+
messages: [ { role: 'user', content: 'Hi' } ],
|
|
290
|
+
model: 'llama3.1:8b',
|
|
291
|
+
temperature: 0.1, # forwarded into body[:options]
|
|
292
|
+
max_tokens: 256, # forwarded into body[:options]
|
|
293
|
+
path: 'api/chat' # optional: override endpoint path
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
# Note: `ollama: { options: ... }` is ignored; use top-level kwargs instead.
|
|
297
|
+
```
|
|
298
|
+
|
|
227
299
|
**Using a JSON Schema for Structured Output**
|
|
228
300
|
|
|
229
301
|
For cases where you need structured output (e.g., for returning specific fields or formatted responses), you can pass a `json_schema` parameter. The schema ensures that the completion conforms to a predefined structure:
|
|
@@ -22,6 +22,7 @@ module Spectre
|
|
|
22
22
|
# @param tools [Array<Hash>, nil] An optional array of tool definitions for function calling
|
|
23
23
|
# @param tool_choice [Hash, nil] Optional tool_choice to force a specific tool use (e.g., { type: 'tool', name: 'record_summary' })
|
|
24
24
|
# @param args [Hash, nil] optional arguments like read_timeout and open_timeout. Provide max_tokens at the top level only.
|
|
25
|
+
# Any additional kwargs (e.g., temperature:, top_p:) will be forwarded into the request body.
|
|
25
26
|
# @return [Hash] The parsed response including any tool calls or content
|
|
26
27
|
# @raise [APIKeyNotConfiguredError] If the API key is not set
|
|
27
28
|
# @raise [RuntimeError] For general API errors or unexpected issues
|
|
@@ -44,7 +45,9 @@ module Spectre
|
|
|
44
45
|
})
|
|
45
46
|
|
|
46
47
|
max_tokens = args[:max_tokens] || 1024
|
|
47
|
-
|
|
48
|
+
# Forward extra args (like temperature) into the body, excluding control/network keys
|
|
49
|
+
forwarded = args.reject { |k, _| [:read_timeout, :open_timeout, :max_tokens, :tool_choice].include?(k) }
|
|
50
|
+
request.body = generate_body(messages, model, json_schema, max_tokens, tools, tool_choice, forwarded).to_json
|
|
48
51
|
response = http.request(request)
|
|
49
52
|
|
|
50
53
|
unless response.is_a?(Net::HTTPSuccess)
|
|
@@ -83,7 +86,7 @@ module Spectre
|
|
|
83
86
|
# @param max_tokens [Integer] The maximum number of tokens for the completion
|
|
84
87
|
# @param tools [Array<Hash>, nil] An optional array of tool definitions for function calling
|
|
85
88
|
# @return [Hash] The body for the API request
|
|
86
|
-
def self.generate_body(messages, model, json_schema, max_tokens, tools, tool_choice)
|
|
89
|
+
def self.generate_body(messages, model, json_schema, max_tokens, tools, tool_choice, forwarded)
|
|
87
90
|
system_prompts, chat_messages = partition_system_and_chat(messages)
|
|
88
91
|
|
|
89
92
|
body = {
|
|
@@ -125,6 +128,11 @@ module Spectre
|
|
|
125
128
|
body[:tools] = tools if tools && !body.key?(:tools)
|
|
126
129
|
body[:tool_choice] = tool_choice if tool_choice
|
|
127
130
|
|
|
131
|
+
# Merge any extra forwarded options (e.g., temperature, top_p)
|
|
132
|
+
if forwarded && !forwarded.empty?
|
|
133
|
+
body.merge!(forwarded.transform_keys(&:to_sym))
|
|
134
|
+
end
|
|
135
|
+
|
|
128
136
|
body
|
|
129
137
|
end
|
|
130
138
|
|
|
@@ -19,6 +19,7 @@ module Spectre
|
|
|
19
19
|
# @param json_schema [Hash, nil] An optional JSON schema to enforce structured output (OpenAI-compatible "response_format")
|
|
20
20
|
# @param tools [Array<Hash>, nil] An optional array of tool definitions for function calling
|
|
21
21
|
# @param args [Hash, nil] optional arguments like read_timeout and open_timeout. Provide max_tokens at the top level only.
|
|
22
|
+
# Any additional kwargs (e.g., temperature:, top_p:) will be forwarded into the request body.
|
|
22
23
|
# @return [Hash] The parsed response including any function calls or content
|
|
23
24
|
# @raise [APIKeyNotConfiguredError] If the API key is not set
|
|
24
25
|
# @raise [RuntimeError] For general API errors or unexpected issues
|
|
@@ -40,7 +41,9 @@ module Spectre
|
|
|
40
41
|
})
|
|
41
42
|
|
|
42
43
|
max_tokens = args[:max_tokens]
|
|
43
|
-
|
|
44
|
+
# Forward extra args (like temperature) into the body, excluding control/network keys
|
|
45
|
+
forwarded = args.reject { |k, _| [:read_timeout, :open_timeout, :max_tokens].include?(k) }
|
|
46
|
+
request.body = generate_body(messages, model, json_schema, max_tokens, tools, forwarded).to_json
|
|
44
47
|
response = http.request(request)
|
|
45
48
|
|
|
46
49
|
unless response.is_a?(Net::HTTPSuccess)
|
|
@@ -75,7 +78,7 @@ module Spectre
|
|
|
75
78
|
end
|
|
76
79
|
|
|
77
80
|
# Helper method to generate the request body (OpenAI-compatible)
|
|
78
|
-
def self.generate_body(messages, model, json_schema, max_tokens, tools)
|
|
81
|
+
def self.generate_body(messages, model, json_schema, max_tokens, tools, forwarded)
|
|
79
82
|
body = {
|
|
80
83
|
model: model,
|
|
81
84
|
messages: messages
|
|
@@ -85,6 +88,11 @@ module Spectre
|
|
|
85
88
|
body[:response_format] = { type: 'json_schema', json_schema: json_schema } if json_schema
|
|
86
89
|
body[:tools] = tools if tools
|
|
87
90
|
|
|
91
|
+
# Merge any extra forwarded options (e.g., temperature, top_p)
|
|
92
|
+
if forwarded && !forwarded.empty?
|
|
93
|
+
body.merge!(forwarded.transform_keys(&:to_sym))
|
|
94
|
+
end
|
|
95
|
+
|
|
88
96
|
body
|
|
89
97
|
end
|
|
90
98
|
|
|
@@ -17,9 +17,9 @@ module Spectre
|
|
|
17
17
|
# @param model [String] The model to be used for generating completions, defaults to DEFAULT_MODEL
|
|
18
18
|
# @param json_schema [Hash, nil] An optional JSON schema to enforce structured output
|
|
19
19
|
# @param tools [Array<Hash>, nil] An optional array of tool definitions for function calling
|
|
20
|
-
# @param args [Hash, nil] optional arguments like read_timeout and open_timeout.
|
|
21
|
-
#
|
|
22
|
-
# @param
|
|
20
|
+
# @param args [Hash, nil] optional arguments like read_timeout and open_timeout.
|
|
21
|
+
# Any additional top-level kwargs (e.g., temperature:, max_tokens:) will be forwarded into body[:options], same as other providers forward into body.
|
|
22
|
+
# @param path [String, nil] Top-level path override for the Ollama API endpoint, defaults to API_PATH
|
|
23
23
|
# @return [Hash] The parsed response including any function calls or content
|
|
24
24
|
# @raise [HostNotConfiguredError] If the API host is not set in the provider configuration.
|
|
25
25
|
# @raise [APIKeyNotConfiguredError] If the API key is not set
|
|
@@ -32,7 +32,7 @@ module Spectre
|
|
|
32
32
|
|
|
33
33
|
validate_messages!(messages)
|
|
34
34
|
|
|
35
|
-
path = args
|
|
35
|
+
path = args[:path] || API_PATH
|
|
36
36
|
uri = URI.join(api_host, path)
|
|
37
37
|
http = Net::HTTP.new(uri.host, uri.port)
|
|
38
38
|
http.use_ssl = true if uri.scheme == 'https'
|
|
@@ -44,7 +44,13 @@ module Spectre
|
|
|
44
44
|
'Authorization' => "Bearer #{api_key}"
|
|
45
45
|
})
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
# Forward extra top-level args (like temperature, max_tokens) into body[:options],
|
|
48
|
+
# excluding control/network keys and the request path override.
|
|
49
|
+
forwarded = args.reject { |k, _| [:read_timeout, :open_timeout, :path].include?(k) }
|
|
50
|
+
options = nil
|
|
51
|
+
if forwarded && !forwarded.empty?
|
|
52
|
+
options = forwarded.transform_keys(&:to_sym)
|
|
53
|
+
end
|
|
48
54
|
request.body = generate_body(messages, model, json_schema, tools, options).to_json
|
|
49
55
|
response = http.request(request)
|
|
50
56
|
|
|
@@ -18,6 +18,7 @@ module Spectre
|
|
|
18
18
|
# @param json_schema [Hash, nil] An optional JSON schema to enforce structured output
|
|
19
19
|
# @param tools [Array<Hash>, nil] An optional array of tool definitions for function calling
|
|
20
20
|
# @param args [Hash, nil] optional arguments like read_timeout and open_timeout. Provide max_tokens at the top level only.
|
|
21
|
+
# Any additional kwargs (e.g., temperature:, top_p:) will be forwarded into the request body.
|
|
21
22
|
# @return [Hash] The parsed response including any function calls or content
|
|
22
23
|
# @raise [APIKeyNotConfiguredError] If the API key is not set
|
|
23
24
|
# @raise [RuntimeError] For general API errors or unexpected issues
|
|
@@ -39,7 +40,9 @@ module Spectre
|
|
|
39
40
|
})
|
|
40
41
|
|
|
41
42
|
max_tokens = args[:max_tokens]
|
|
42
|
-
|
|
43
|
+
# Forward extra args (like temperature) into the body, excluding control/network keys
|
|
44
|
+
forwarded = args.reject { |k, _| [:read_timeout, :open_timeout, :max_tokens].include?(k) }
|
|
45
|
+
request.body = generate_body(messages, model, json_schema, max_tokens, tools, forwarded).to_json
|
|
43
46
|
response = http.request(request)
|
|
44
47
|
|
|
45
48
|
unless response.is_a?(Net::HTTPSuccess)
|
|
@@ -82,7 +85,7 @@ module Spectre
|
|
|
82
85
|
# @param max_tokens [Integer, nil] The maximum number of tokens for the completion
|
|
83
86
|
# @param tools [Array<Hash>, nil] An optional array of tool definitions for function calling
|
|
84
87
|
# @return [Hash] The body for the API request
|
|
85
|
-
def self.generate_body(messages, model, json_schema, max_tokens, tools)
|
|
88
|
+
def self.generate_body(messages, model, json_schema, max_tokens, tools, forwarded)
|
|
86
89
|
body = {
|
|
87
90
|
model: model,
|
|
88
91
|
messages: messages
|
|
@@ -92,6 +95,11 @@ module Spectre
|
|
|
92
95
|
body[:response_format] = { type: 'json_schema', json_schema: json_schema } if json_schema
|
|
93
96
|
body[:tools] = tools if tools # Add the tools to the request body if provided
|
|
94
97
|
|
|
98
|
+
# Merge any extra forwarded options (e.g., temperature, top_p)
|
|
99
|
+
if forwarded && !forwarded.empty?
|
|
100
|
+
body.merge!(forwarded.transform_keys(&:to_sym))
|
|
101
|
+
end
|
|
102
|
+
|
|
95
103
|
body
|
|
96
104
|
end
|
|
97
105
|
|
|
@@ -18,6 +18,7 @@ module Spectre
|
|
|
18
18
|
# @param json_schema [Hash, nil] An optional JSON schema to enforce structured output (OpenAI-compatible)
|
|
19
19
|
# @param tools [Array<Hash>, nil] An optional array of tool definitions for function calling
|
|
20
20
|
# @param args [Hash, nil] optional arguments like read_timeout and open_timeout. Provide max_tokens at the top level only.
|
|
21
|
+
# Any additional kwargs (e.g., temperature:, top_p:) will be forwarded into the request body.
|
|
21
22
|
# @return [Hash] The parsed response including any tool calls or content
|
|
22
23
|
# @raise [APIKeyNotConfiguredError] If the API key is not set
|
|
23
24
|
# @raise [RuntimeError] For general API errors or unexpected issues
|
|
@@ -44,7 +45,9 @@ module Spectre
|
|
|
44
45
|
request = Net::HTTP::Post.new(uri.path, headers)
|
|
45
46
|
|
|
46
47
|
max_tokens = args[:max_tokens]
|
|
47
|
-
|
|
48
|
+
# Forward extra args into body, excluding control/network keys
|
|
49
|
+
forwarded = args.reject { |k, _| [:read_timeout, :open_timeout, :max_tokens].include?(k) }
|
|
50
|
+
request.body = generate_body(messages, model, json_schema, max_tokens, tools, forwarded).to_json
|
|
48
51
|
response = http.request(request)
|
|
49
52
|
|
|
50
53
|
unless response.is_a?(Net::HTTPSuccess)
|
|
@@ -66,7 +69,7 @@ module Spectre
|
|
|
66
69
|
raise ArgumentError, 'Messages cannot be empty.' if messages.empty?
|
|
67
70
|
end
|
|
68
71
|
|
|
69
|
-
def self.generate_body(messages, model, json_schema, max_tokens, tools)
|
|
72
|
+
def self.generate_body(messages, model, json_schema, max_tokens, tools, forwarded)
|
|
70
73
|
body = {
|
|
71
74
|
model: model,
|
|
72
75
|
messages: messages
|
|
@@ -74,6 +77,9 @@ module Spectre
|
|
|
74
77
|
body[:max_tokens] = max_tokens if max_tokens
|
|
75
78
|
body[:response_format] = { type: 'json_schema', json_schema: json_schema } if json_schema
|
|
76
79
|
body[:tools] = tools if tools
|
|
80
|
+
if forwarded && !forwarded.empty?
|
|
81
|
+
body.merge!(forwarded.transform_keys(&:to_sym))
|
|
82
|
+
end
|
|
77
83
|
body
|
|
78
84
|
end
|
|
79
85
|
|
data/lib/spectre/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: spectre_ai
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.1.
|
|
4
|
+
version: 2.1.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ilya Klapatok
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2025-
|
|
12
|
+
date: 2025-12-15 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: rspec-rails
|