ruby_llm 1.3.0rc1 → 1.3.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/lib/ruby_llm/active_record/acts_as.rb +66 -148
- data/lib/ruby_llm/aliases.json +170 -42
- data/lib/ruby_llm/attachment.rb +164 -0
- data/lib/ruby_llm/chat.rb +12 -4
- data/lib/ruby_llm/configuration.rb +5 -1
- data/lib/ruby_llm/connection.rb +28 -2
- data/lib/ruby_llm/content.rb +9 -40
- data/lib/ruby_llm/error.rb +1 -0
- data/lib/ruby_llm/image.rb +2 -3
- data/lib/ruby_llm/message.rb +2 -2
- data/lib/ruby_llm/mime_type.rb +67 -0
- data/lib/ruby_llm/model/info.rb +101 -0
- data/lib/ruby_llm/model/modalities.rb +22 -0
- data/lib/ruby_llm/model/pricing.rb +51 -0
- data/lib/ruby_llm/model/pricing_category.rb +48 -0
- data/lib/ruby_llm/model/pricing_tier.rb +34 -0
- data/lib/ruby_llm/model.rb +7 -0
- data/lib/ruby_llm/models.json +2220 -1915
- data/lib/ruby_llm/models.rb +20 -20
- data/lib/ruby_llm/provider.rb +1 -1
- data/lib/ruby_llm/providers/anthropic/media.rb +14 -3
- data/lib/ruby_llm/providers/anthropic/models.rb +1 -1
- data/lib/ruby_llm/providers/bedrock/media.rb +7 -4
- data/lib/ruby_llm/providers/bedrock/models.rb +2 -2
- data/lib/ruby_llm/providers/gemini/images.rb +3 -2
- data/lib/ruby_llm/providers/gemini/media.rb +12 -24
- data/lib/ruby_llm/providers/gemini/models.rb +1 -1
- data/lib/ruby_llm/providers/ollama/media.rb +8 -4
- data/lib/ruby_llm/providers/openai/capabilities.rb +1 -1
- data/lib/ruby_llm/providers/openai/images.rb +3 -2
- data/lib/ruby_llm/providers/openai/media.rb +18 -8
- data/lib/ruby_llm/providers/openai/models.rb +1 -1
- data/lib/ruby_llm/providers/openrouter/models.rb +1 -1
- data/lib/ruby_llm/streaming.rb +46 -11
- data/lib/ruby_llm/utils.rb +14 -9
- data/lib/ruby_llm/version.rb +1 -1
- data/lib/tasks/aliases.rake +235 -0
- data/lib/tasks/release.rake +32 -0
- metadata +40 -25
- data/lib/ruby_llm/attachments/audio.rb +0 -12
- data/lib/ruby_llm/attachments/image.rb +0 -9
- data/lib/ruby_llm/attachments/pdf.rb +0 -9
- data/lib/ruby_llm/attachments.rb +0 -78
- data/lib/ruby_llm/mime_types.rb +0 -713
- data/lib/ruby_llm/model_info.rb +0 -237
- data/lib/tasks/{models.rake → models_update.rake} +13 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8a1f6385e98e9396c7f9d8021bd2e574f5f8c8aa1cc05c7f10311e2059101017
|
4
|
+
data.tar.gz: e7617280adc17488f9dbc810b424b22ee21f36c0684f0a5f37762dd290d6c0de
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 80bcef1cb440519b7eb146bd4064f8eb5a40cf1fd5e309ac582c6be8a3aee0a33b244e8c4961bc69ac763b2665adab918238a0d8787b41c2fb6e5e7fd6343ae3
|
7
|
+
data.tar.gz: 3d95b550d6d879ad29e20bb328cb09d7191b4055180cba95e237ddab2d1173845463d62e407c777d6b76425958531fb6e7abc664939478c9e89b41565971ad2b
|
@@ -20,8 +20,7 @@ module RubyLLM
|
|
20
20
|
class_name: @message_class,
|
21
21
|
dependent: :destroy
|
22
22
|
|
23
|
-
delegate :add_message,
|
24
|
-
to: :to_llm
|
23
|
+
delegate :add_message, to: :to_llm
|
25
24
|
end
|
26
25
|
|
27
26
|
def acts_as_message(chat_class: 'Chat',
|
@@ -88,26 +87,18 @@ module RubyLLM
|
|
88
87
|
@chat ||= RubyLLM.chat(model: model_id)
|
89
88
|
@chat.reset_messages!
|
90
89
|
|
91
|
-
# Load existing messages into chat
|
92
90
|
messages.each do |msg|
|
93
91
|
@chat.add_message(msg.to_llm)
|
94
92
|
end
|
95
93
|
|
96
|
-
# Set up message persistence
|
97
94
|
@chat.on_new_message { persist_new_message }
|
98
95
|
.on_end_message { |msg| persist_message_completion(msg) }
|
99
96
|
end
|
100
97
|
|
101
98
|
def with_instructions(instructions, replace: false)
|
102
99
|
transaction do
|
103
|
-
# If replace is true, remove existing system messages
|
104
100
|
messages.where(role: :system).destroy_all if replace
|
105
|
-
|
106
|
-
# Create the new system message
|
107
|
-
messages.create!(
|
108
|
-
role: :system,
|
109
|
-
content: instructions
|
110
|
-
)
|
101
|
+
messages.create!(role: :system, content: instructions)
|
111
102
|
end
|
112
103
|
to_llm.with_instructions(instructions)
|
113
104
|
self
|
@@ -124,7 +115,7 @@ module RubyLLM
|
|
124
115
|
end
|
125
116
|
|
126
117
|
def with_model(...)
|
127
|
-
to_llm.with_model(...)
|
118
|
+
update(model_id: to_llm.with_model(...).model.id)
|
128
119
|
self
|
129
120
|
end
|
130
121
|
|
@@ -133,6 +124,11 @@ module RubyLLM
|
|
133
124
|
self
|
134
125
|
end
|
135
126
|
|
127
|
+
def with_context(...)
|
128
|
+
to_llm.with_context(...)
|
129
|
+
self
|
130
|
+
end
|
131
|
+
|
136
132
|
def on_new_message(...)
|
137
133
|
to_llm.on_new_message(...)
|
138
134
|
self
|
@@ -144,21 +140,8 @@ module RubyLLM
|
|
144
140
|
end
|
145
141
|
|
146
142
|
def create_user_message(content, with: nil)
|
147
|
-
message_record = messages.create!(
|
148
|
-
|
149
|
-
content: content
|
150
|
-
)
|
151
|
-
|
152
|
-
if with.present?
|
153
|
-
files = Array(with).reject(&:blank?)
|
154
|
-
|
155
|
-
if files.any? && files.first.is_a?(ActionDispatch::Http::UploadedFile)
|
156
|
-
message_record.attachments.attach(files)
|
157
|
-
else
|
158
|
-
attach_files(message_record, process_attachments(with))
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
143
|
+
message_record = messages.create!(role: :user, content: content)
|
144
|
+
persist_content(message_record, with) if with.present?
|
162
145
|
message_record
|
163
146
|
end
|
164
147
|
|
@@ -182,21 +165,16 @@ module RubyLLM
|
|
182
165
|
private
|
183
166
|
|
184
167
|
def persist_new_message
|
185
|
-
@message = messages.create!(
|
186
|
-
role: :assistant,
|
187
|
-
content: String.new
|
188
|
-
)
|
168
|
+
@message = messages.create!(role: :assistant, content: String.new)
|
189
169
|
end
|
190
170
|
|
191
171
|
def persist_message_completion(message)
|
192
172
|
return unless message
|
193
173
|
|
194
|
-
if message.tool_call_id
|
195
|
-
tool_call_id = self.class.tool_call_class.constantize.find_by(tool_call_id: message.tool_call_id)&.id
|
196
|
-
end
|
174
|
+
tool_call_id = find_tool_call_id(message.tool_call_id) if message.tool_call_id
|
197
175
|
|
198
176
|
transaction do
|
199
|
-
@message.update(
|
177
|
+
@message.update!(
|
200
178
|
role: message.role,
|
201
179
|
content: message.content,
|
202
180
|
model_id: message.model_id,
|
@@ -217,84 +195,46 @@ module RubyLLM
|
|
217
195
|
end
|
218
196
|
end
|
219
197
|
|
220
|
-
def
|
221
|
-
|
222
|
-
|
223
|
-
result = {}
|
224
|
-
files = Array(attachments)
|
225
|
-
|
226
|
-
files.each do |file|
|
227
|
-
content_type = if file.respond_to?(:content_type)
|
228
|
-
file.content_type
|
229
|
-
elsif file.is_a?(ActiveStorage::Attachment)
|
230
|
-
file.blob.content_type
|
231
|
-
else
|
232
|
-
RubyLLM::MimeTypes.detect_from_path(file.to_s)
|
233
|
-
end
|
234
|
-
|
235
|
-
if RubyLLM::MimeTypes.image?(content_type)
|
236
|
-
result[:image] ||= []
|
237
|
-
result[:image] << file
|
238
|
-
elsif RubyLLM::MimeTypes.audio?(content_type)
|
239
|
-
result[:audio] ||= []
|
240
|
-
result[:audio] << file
|
241
|
-
else
|
242
|
-
# Default to PDF for unknown types
|
243
|
-
result[:pdf] ||= []
|
244
|
-
result[:pdf] << file
|
245
|
-
end
|
246
|
-
end
|
247
|
-
|
248
|
-
result
|
198
|
+
def find_tool_call_id(tool_call_id)
|
199
|
+
self.class.tool_call_class.constantize.find_by(tool_call_id: tool_call_id)&.id
|
249
200
|
end
|
250
201
|
|
251
|
-
def
|
252
|
-
return unless
|
202
|
+
def persist_content(message_record, attachments)
|
203
|
+
return unless message_record.respond_to?(:attachments)
|
253
204
|
|
254
|
-
|
255
|
-
|
256
|
-
attach_file(message, file_source)
|
257
|
-
end
|
258
|
-
end
|
205
|
+
attachables = prepare_for_active_storage(attachments)
|
206
|
+
message_record.attachments.attach(attachables) if attachables.any?
|
259
207
|
end
|
260
208
|
|
261
|
-
def
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
elsif file_source.respond_to?(:read)
|
275
|
-
# Handle various file source types
|
276
|
-
message.attachments.attach(
|
277
|
-
io: file_source,
|
278
|
-
filename: extract_filename(file_source),
|
279
|
-
content_type: RubyLLM::MimeTypes.detect_from_path(extract_filename(file_source))
|
280
|
-
) # Already a file-like object
|
281
|
-
elsif file_source.is_a?(::ActiveStorage::Attachment)
|
282
|
-
# Copy from existing ActiveStorage attachment
|
283
|
-
message.attachments.attach(file_source.blob)
|
284
|
-
elsif file_source.is_a?(::ActiveStorage::Blob)
|
285
|
-
message.attachments.attach(file_source)
|
286
|
-
else
|
287
|
-
# Local file path
|
288
|
-
message.attachments.attach(
|
289
|
-
io: File.open(file_source),
|
290
|
-
filename: File.basename(file_source),
|
291
|
-
content_type: RubyLLM::MimeTypes.detect_from_path(file_source)
|
292
|
-
)
|
293
|
-
end
|
209
|
+
def prepare_for_active_storage(attachments)
|
210
|
+
Utils.to_safe_array(attachments).filter_map do |attachment|
|
211
|
+
case attachment
|
212
|
+
when ActionDispatch::Http::UploadedFile, ActiveStorage::Blob
|
213
|
+
attachment
|
214
|
+
when ActiveStorage::Attached::One, ActiveStorage::Attached::Many
|
215
|
+
attachment.blobs
|
216
|
+
when Hash
|
217
|
+
attachment.values.map { |v| prepare_for_active_storage(v) }
|
218
|
+
else
|
219
|
+
convert_to_active_storage_format(attachment)
|
220
|
+
end
|
221
|
+
end.flatten.compact
|
294
222
|
end
|
295
223
|
|
296
|
-
def
|
297
|
-
|
224
|
+
def convert_to_active_storage_format(source)
|
225
|
+
return if source.blank?
|
226
|
+
|
227
|
+
# Let RubyLLM::Attachment handle the heavy lifting
|
228
|
+
attachment = RubyLLM::Attachment.new(source)
|
229
|
+
|
230
|
+
{
|
231
|
+
io: StringIO.new(attachment.content),
|
232
|
+
filename: attachment.filename,
|
233
|
+
content_type: attachment.mime_type
|
234
|
+
}
|
235
|
+
rescue StandardError => e
|
236
|
+
RubyLLM.logger.warn "Failed to process attachment #{source}: #{e.message}"
|
237
|
+
nil
|
298
238
|
end
|
299
239
|
end
|
300
240
|
|
@@ -319,6 +259,8 @@ module RubyLLM
|
|
319
259
|
)
|
320
260
|
end
|
321
261
|
|
262
|
+
private
|
263
|
+
|
322
264
|
def extract_tool_calls
|
323
265
|
tool_calls.to_h do |tool_call|
|
324
266
|
[
|
@@ -336,55 +278,31 @@ module RubyLLM
|
|
336
278
|
parent_tool_call&.tool_call_id
|
337
279
|
end
|
338
280
|
|
339
|
-
def extract_content
|
281
|
+
def extract_content
|
340
282
|
return content unless respond_to?(:attachments) && attachments.attached?
|
341
283
|
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
attachment_data = if attachment.metadata&.key?('original_url')
|
349
|
-
attachment.metadata['original_url']
|
350
|
-
elsif defined?(ActiveJob) && caller.any? { |c| c.include?('active_job') }
|
351
|
-
# We're in a background job - need to download the data
|
352
|
-
temp_file = Tempfile.new([File.basename(attachment.filename.to_s, '.*'),
|
353
|
-
File.extname(attachment.filename.to_s)])
|
354
|
-
temp_file.binmode
|
355
|
-
temp_file.write(attachment.download)
|
356
|
-
temp_file.flush
|
357
|
-
temp_file.rewind
|
358
|
-
|
359
|
-
# Store the tempfile reference in the instance variable to prevent GC
|
360
|
-
@_tempfiles << temp_file
|
361
|
-
|
362
|
-
# Return the file object itself, not just the path
|
363
|
-
temp_file
|
364
|
-
else
|
365
|
-
blob_path_for(attachment)
|
366
|
-
end
|
367
|
-
|
368
|
-
if RubyLLM::MimeTypes.image?(attachment.content_type)
|
369
|
-
content_obj.add_image(attachment_data)
|
370
|
-
elsif RubyLLM::MimeTypes.audio?(attachment.content_type)
|
371
|
-
content_obj.add_audio(attachment_data)
|
372
|
-
elsif RubyLLM::MimeTypes.pdf?(attachment.content_type)
|
373
|
-
content_obj.add_pdf(attachment_data)
|
284
|
+
RubyLLM::Content.new(content).tap do |content_obj|
|
285
|
+
@_tempfiles = []
|
286
|
+
|
287
|
+
attachments.each do |attachment|
|
288
|
+
tempfile = download_attachment(attachment)
|
289
|
+
content_obj.add_attachment(tempfile, filename: attachment.filename.to_s)
|
374
290
|
end
|
375
291
|
end
|
376
|
-
|
377
|
-
content_obj
|
378
292
|
end
|
379
293
|
|
380
|
-
|
294
|
+
def download_attachment(attachment)
|
295
|
+
ext = File.extname(attachment.filename.to_s)
|
296
|
+
basename = File.basename(attachment.filename.to_s, ext)
|
297
|
+
tempfile = Tempfile.new([basename, ext])
|
298
|
+
tempfile.binmode
|
381
299
|
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
300
|
+
attachment.download { |chunk| tempfile.write(chunk) }
|
301
|
+
|
302
|
+
tempfile.flush
|
303
|
+
tempfile.rewind
|
304
|
+
@_tempfiles << tempfile
|
305
|
+
tempfile
|
388
306
|
end
|
389
307
|
end
|
390
308
|
end
|
data/lib/ruby_llm/aliases.json
CHANGED
@@ -1,80 +1,208 @@
|
|
1
1
|
{
|
2
|
-
"
|
3
|
-
"
|
4
|
-
"
|
5
|
-
|
2
|
+
"chatgpt-4o": {
|
3
|
+
"openai": "chatgpt-4o-latest",
|
4
|
+
"openrouter": "openai/chatgpt-4o-latest"
|
5
|
+
},
|
6
|
+
"claude-2.0": {
|
7
|
+
"anthropic": "claude-2.0",
|
8
|
+
"openrouter": "anthropic/claude-2.0",
|
9
|
+
"bedrock": "anthropic.claude-v2:1:200k"
|
10
|
+
},
|
11
|
+
"claude-2.1": {
|
12
|
+
"anthropic": "claude-2.1",
|
13
|
+
"openrouter": "anthropic/claude-2.1",
|
14
|
+
"bedrock": "anthropic.claude-v2:1:200k"
|
6
15
|
},
|
7
16
|
"claude-3-5-haiku": {
|
8
17
|
"anthropic": "claude-3-5-haiku-20241022",
|
9
|
-
"
|
10
|
-
"
|
18
|
+
"openrouter": "anthropic/claude-3.5-haiku",
|
19
|
+
"bedrock": "anthropic.claude-3-5-haiku-20241022-v1:0"
|
20
|
+
},
|
21
|
+
"claude-3-5-sonnet": {
|
22
|
+
"anthropic": "claude-3-5-sonnet-20241022",
|
23
|
+
"openrouter": "anthropic/claude-3.5-sonnet",
|
24
|
+
"bedrock": "anthropic.claude-3-5-sonnet-20240620-v1:0:200k"
|
11
25
|
},
|
12
26
|
"claude-3-7-sonnet": {
|
13
27
|
"anthropic": "claude-3-7-sonnet-20250219",
|
14
|
-
"
|
15
|
-
"
|
28
|
+
"openrouter": "anthropic/claude-3.7-sonnet",
|
29
|
+
"bedrock": "us.anthropic.claude-3-7-sonnet-20250219-v1:0"
|
30
|
+
},
|
31
|
+
"claude-3-haiku": {
|
32
|
+
"anthropic": "claude-3-haiku-20240307",
|
33
|
+
"openrouter": "anthropic/claude-3-haiku",
|
34
|
+
"bedrock": "anthropic.claude-3-haiku-20240307-v1:0:200k"
|
16
35
|
},
|
17
36
|
"claude-3-opus": {
|
18
37
|
"anthropic": "claude-3-opus-20240229",
|
19
|
-
"
|
38
|
+
"openrouter": "anthropic/claude-3-opus",
|
39
|
+
"bedrock": "anthropic.claude-3-opus-20240229-v1:0:200k"
|
20
40
|
},
|
21
41
|
"claude-3-sonnet": {
|
22
42
|
"anthropic": "claude-3-sonnet-20240229",
|
23
|
-
"
|
43
|
+
"openrouter": "anthropic/claude-3-sonnet",
|
44
|
+
"bedrock": "anthropic.claude-3-sonnet-20240229-v1:0:200k"
|
24
45
|
},
|
25
|
-
"claude-
|
26
|
-
"anthropic": "claude-
|
27
|
-
"
|
46
|
+
"claude-opus-4": {
|
47
|
+
"anthropic": "claude-opus-4-20250514",
|
48
|
+
"openrouter": "anthropic/claude-opus-4",
|
49
|
+
"bedrock": "us.anthropic.claude-opus-4-20250514-v1:0"
|
28
50
|
},
|
29
|
-
"claude-
|
30
|
-
"anthropic": "claude-
|
31
|
-
"
|
32
|
-
"
|
51
|
+
"claude-sonnet-4": {
|
52
|
+
"anthropic": "claude-sonnet-4-20250514",
|
53
|
+
"openrouter": "anthropic/claude-sonnet-4",
|
54
|
+
"bedrock": "us.anthropic.claude-sonnet-4-20250514-v1:0"
|
33
55
|
},
|
34
|
-
"
|
35
|
-
"
|
36
|
-
"
|
37
|
-
"openrouter": "anthropic/claude-2"
|
56
|
+
"deepseek-chat": {
|
57
|
+
"deepseek": "deepseek-chat",
|
58
|
+
"openrouter": "deepseek/deepseek-chat"
|
38
59
|
},
|
39
|
-
"
|
40
|
-
"
|
41
|
-
"
|
42
|
-
|
60
|
+
"gemini-2.0-flash-001": {
|
61
|
+
"gemini": "gemini-2.0-flash-001",
|
62
|
+
"openrouter": "google/gemini-2.0-flash-001"
|
63
|
+
},
|
64
|
+
"gemini-2.0-flash-lite-001": {
|
65
|
+
"gemini": "gemini-2.0-flash-lite-001",
|
66
|
+
"openrouter": "google/gemini-2.0-flash-lite-001"
|
67
|
+
},
|
68
|
+
"gemini-2.5-flash-preview-05-20": {
|
69
|
+
"gemini": "gemini-2.5-flash-preview-05-20",
|
70
|
+
"openrouter": "google/gemini-2.5-flash-preview-05-20"
|
71
|
+
},
|
72
|
+
"gemini-2.5-pro-exp-03-25": {
|
73
|
+
"gemini": "gemini-2.5-pro-exp-03-25",
|
74
|
+
"openrouter": "google/gemini-2.5-pro-exp-03-25"
|
75
|
+
},
|
76
|
+
"gemma-3-12b-it": {
|
77
|
+
"gemini": "gemma-3-12b-it",
|
78
|
+
"openrouter": "google/gemma-3-12b-it"
|
79
|
+
},
|
80
|
+
"gemma-3-27b-it": {
|
81
|
+
"gemini": "gemma-3-27b-it",
|
82
|
+
"openrouter": "google/gemma-3-27b-it"
|
83
|
+
},
|
84
|
+
"gemma-3-4b-it": {
|
85
|
+
"gemini": "gemma-3-4b-it",
|
86
|
+
"openrouter": "google/gemma-3-4b-it"
|
87
|
+
},
|
88
|
+
"gpt-3.5-turbo": {
|
89
|
+
"openai": "gpt-3.5-turbo",
|
90
|
+
"openrouter": "openai/gpt-3.5-turbo"
|
91
|
+
},
|
92
|
+
"gpt-3.5-turbo-0125": {
|
93
|
+
"openai": "gpt-3.5-turbo-0125",
|
94
|
+
"openrouter": "openai/gpt-3.5-turbo-0125"
|
95
|
+
},
|
96
|
+
"gpt-3.5-turbo-1106": {
|
97
|
+
"openai": "gpt-3.5-turbo-1106",
|
98
|
+
"openrouter": "openai/gpt-3.5-turbo-1106"
|
99
|
+
},
|
100
|
+
"gpt-3.5-turbo-16k": {
|
101
|
+
"openai": "gpt-3.5-turbo-16k",
|
102
|
+
"openrouter": "openai/gpt-3.5-turbo-16k"
|
103
|
+
},
|
104
|
+
"gpt-3.5-turbo-instruct": {
|
105
|
+
"openai": "gpt-3.5-turbo-instruct",
|
106
|
+
"openrouter": "openai/gpt-3.5-turbo-instruct"
|
107
|
+
},
|
108
|
+
"gpt-4": {
|
109
|
+
"openai": "gpt-4",
|
110
|
+
"openrouter": "openai/gpt-4"
|
111
|
+
},
|
112
|
+
"gpt-4-1106-preview": {
|
113
|
+
"openai": "gpt-4-1106-preview",
|
114
|
+
"openrouter": "openai/gpt-4-1106-preview"
|
115
|
+
},
|
116
|
+
"gpt-4-turbo": {
|
117
|
+
"openai": "gpt-4-turbo",
|
118
|
+
"openrouter": "openai/gpt-4-turbo"
|
119
|
+
},
|
120
|
+
"gpt-4-turbo-preview": {
|
121
|
+
"openai": "gpt-4-turbo-preview",
|
122
|
+
"openrouter": "openai/gpt-4-turbo-preview"
|
123
|
+
},
|
124
|
+
"gpt-4.1": {
|
125
|
+
"openai": "gpt-4.1",
|
126
|
+
"openrouter": "openai/gpt-4.1"
|
127
|
+
},
|
128
|
+
"gpt-4.1-mini": {
|
129
|
+
"openai": "gpt-4.1-mini",
|
130
|
+
"openrouter": "openai/gpt-4.1-mini"
|
131
|
+
},
|
132
|
+
"gpt-4.1-nano": {
|
133
|
+
"openai": "gpt-4.1-nano",
|
134
|
+
"openrouter": "openai/gpt-4.1-nano"
|
135
|
+
},
|
136
|
+
"gpt-4.5-preview": {
|
137
|
+
"openai": "gpt-4.5-preview",
|
138
|
+
"openrouter": "openai/gpt-4.5-preview"
|
43
139
|
},
|
44
140
|
"gpt-4o": {
|
45
141
|
"openai": "gpt-4o",
|
46
142
|
"openrouter": "openai/gpt-4o"
|
47
143
|
},
|
144
|
+
"gpt-4o-2024-05-13": {
|
145
|
+
"openai": "gpt-4o-2024-05-13",
|
146
|
+
"openrouter": "openai/gpt-4o-2024-05-13"
|
147
|
+
},
|
148
|
+
"gpt-4o-2024-08-06": {
|
149
|
+
"openai": "gpt-4o-2024-08-06",
|
150
|
+
"openrouter": "openai/gpt-4o-2024-08-06"
|
151
|
+
},
|
152
|
+
"gpt-4o-2024-11-20": {
|
153
|
+
"openai": "gpt-4o-2024-11-20",
|
154
|
+
"openrouter": "openai/gpt-4o-2024-11-20"
|
155
|
+
},
|
48
156
|
"gpt-4o-mini": {
|
49
157
|
"openai": "gpt-4o-mini",
|
50
158
|
"openrouter": "openai/gpt-4o-mini"
|
51
159
|
},
|
52
|
-
"gpt-
|
53
|
-
"openai": "gpt-
|
54
|
-
"openrouter": "openai/gpt-
|
160
|
+
"gpt-4o-mini-2024-07-18": {
|
161
|
+
"openai": "gpt-4o-mini-2024-07-18",
|
162
|
+
"openrouter": "openai/gpt-4o-mini-2024-07-18"
|
55
163
|
},
|
56
|
-
"
|
57
|
-
"
|
58
|
-
"openrouter": "
|
164
|
+
"gpt-4o-mini-search-preview": {
|
165
|
+
"openai": "gpt-4o-mini-search-preview",
|
166
|
+
"openrouter": "openai/gpt-4o-mini-search-preview"
|
59
167
|
},
|
60
|
-
"
|
61
|
-
"
|
62
|
-
"openrouter": "
|
63
|
-
},
|
64
|
-
"gemini-1.5-pro": {
|
65
|
-
"gemini": "gemini-1.5-pro",
|
66
|
-
"openrouter": "google/gemini-pro-1.5"
|
67
|
-
},
|
68
|
-
"gemini-2.0-flash": {
|
69
|
-
"gemini": "gemini-2.0-flash",
|
70
|
-
"openrouter": "google/gemini-2.0-flash-001"
|
168
|
+
"gpt-4o-search-preview": {
|
169
|
+
"openai": "gpt-4o-search-preview",
|
170
|
+
"openrouter": "openai/gpt-4o-search-preview"
|
71
171
|
},
|
72
172
|
"o1": {
|
73
173
|
"openai": "o1",
|
74
174
|
"openrouter": "openai/o1"
|
75
175
|
},
|
176
|
+
"o1-mini": {
|
177
|
+
"openai": "o1-mini",
|
178
|
+
"openrouter": "openai/o1-mini"
|
179
|
+
},
|
180
|
+
"o1-mini-2024-09-12": {
|
181
|
+
"openai": "o1-mini-2024-09-12",
|
182
|
+
"openrouter": "openai/o1-mini-2024-09-12"
|
183
|
+
},
|
184
|
+
"o1-preview": {
|
185
|
+
"openai": "o1-preview",
|
186
|
+
"openrouter": "openai/o1-preview"
|
187
|
+
},
|
188
|
+
"o1-preview-2024-09-12": {
|
189
|
+
"openai": "o1-preview-2024-09-12",
|
190
|
+
"openrouter": "openai/o1-preview-2024-09-12"
|
191
|
+
},
|
192
|
+
"o1-pro": {
|
193
|
+
"openai": "o1-pro",
|
194
|
+
"openrouter": "openai/o1-pro"
|
195
|
+
},
|
196
|
+
"o3": {
|
197
|
+
"openai": "o3",
|
198
|
+
"openrouter": "openai/o3"
|
199
|
+
},
|
76
200
|
"o3-mini": {
|
77
201
|
"openai": "o3-mini",
|
78
202
|
"openrouter": "openai/o3-mini"
|
203
|
+
},
|
204
|
+
"o4-mini": {
|
205
|
+
"openai": "o4-mini",
|
206
|
+
"openrouter": "openai/o4-mini"
|
79
207
|
}
|
80
208
|
}
|