lluminary 0.1.2 → 0.1.3
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/lluminary/config.rb +1 -6
- data/lib/lluminary/models/base.rb +235 -0
- data/lib/lluminary/models/bedrock/amazon_nova_pro_v1.rb +19 -0
- data/lib/lluminary/models/bedrock/anthropic_claude_instant_v1.rb +17 -0
- data/lib/lluminary/models/bedrock/base.rb +29 -0
- data/lib/lluminary/models/openai/gpt35_turbo.rb +20 -0
- data/lib/lluminary/providers/base.rb +15 -2
- data/lib/lluminary/providers/bedrock.rb +25 -7
- data/lib/lluminary/providers/openai.rb +14 -4
- data/lib/lluminary/providers/test.rb +6 -0
- data/lib/lluminary/schema.rb +51 -0
- data/lib/lluminary/schema_model.rb +54 -0
- data/lib/lluminary/task.rb +11 -77
- data/lib/lluminary.rb +4 -2
- data/spec/examples/meal_suggester_spec.rb +64 -0
- data/spec/lluminary/models/base_spec.rb +581 -0
- data/spec/lluminary/models/bedrock/amazon_nova_pro_v1_spec.rb +30 -0
- data/spec/lluminary/models/bedrock/anthropic_claude_instant_v1_spec.rb +21 -0
- data/spec/lluminary/models/openai/gpt35_turbo_spec.rb +22 -0
- data/spec/lluminary/providers/bedrock_spec.rb +39 -0
- data/spec/lluminary/providers/openai_spec.rb +32 -0
- data/spec/lluminary/providers/test_spec.rb +25 -0
- data/spec/lluminary/schema_model_spec.rb +77 -0
- data/spec/lluminary/schema_spec.rb +146 -0
- data/spec/lluminary/task_spec.rb +18 -550
- data/spec/spec_helper.rb +1 -0
- metadata +44 -9
- data/lib/lluminary/field_description.rb +0 -153
- data/spec/lluminary/field_description_spec.rb +0 -34
- data/spec/lluminary/providers/base_spec.rb +0 -20
@@ -0,0 +1,581 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "spec_helper"
|
3
|
+
|
4
|
+
RSpec.describe Lluminary::Models::Base do
|
5
|
+
let(:model) { described_class.new }
|
6
|
+
|
7
|
+
describe "#compatible_with?" do
|
8
|
+
it "raises NotImplementedError" do
|
9
|
+
expect { model.compatible_with?(:openai) }.to raise_error(
|
10
|
+
NotImplementedError
|
11
|
+
)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#name" do
|
16
|
+
it "raises NotImplementedError" do
|
17
|
+
expect { model.name }.to raise_error(NotImplementedError)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#format_prompt" do
|
22
|
+
let(:task_class) do
|
23
|
+
Class.new(Lluminary::Task) do
|
24
|
+
def task_prompt
|
25
|
+
"Test prompt"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
let(:task) { task_class.new }
|
31
|
+
|
32
|
+
context "with simple field types" do
|
33
|
+
context "with string field type" do
|
34
|
+
before do
|
35
|
+
task_class.output_schema do
|
36
|
+
string :name, description: "The person's name"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
it "formats string field description correctly" do
|
41
|
+
expect(model.format_prompt(task)).to include(<<~DESCRIPTION.chomp)
|
42
|
+
# name
|
43
|
+
Type: string
|
44
|
+
Description: The person's name
|
45
|
+
Example: your name here
|
46
|
+
DESCRIPTION
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context "with integer field type" do
|
51
|
+
before do
|
52
|
+
task_class.output_schema do
|
53
|
+
integer :age, description: "The person's age"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
it "formats integer field description correctly" do
|
58
|
+
expect(model.format_prompt(task)).to include(<<~DESCRIPTION.chomp)
|
59
|
+
# age
|
60
|
+
Type: integer
|
61
|
+
Description: The person's age
|
62
|
+
Example: 0
|
63
|
+
DESCRIPTION
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context "with boolean field type" do
|
68
|
+
before do
|
69
|
+
task_class.output_schema do
|
70
|
+
boolean :active, description: "Whether the person is active"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
it "formats boolean field description correctly" do
|
75
|
+
expect(model.format_prompt(task)).to include(<<~DESCRIPTION.chomp)
|
76
|
+
# active
|
77
|
+
Type: boolean
|
78
|
+
Description: Whether the person is active
|
79
|
+
Example: true
|
80
|
+
DESCRIPTION
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context "with float field type" do
|
85
|
+
before do
|
86
|
+
task_class.output_schema do
|
87
|
+
float :score, description: "The person's score"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
it "formats float field description correctly" do
|
92
|
+
expect(model.format_prompt(task)).to include(<<~DESCRIPTION.chomp)
|
93
|
+
# score
|
94
|
+
Type: float
|
95
|
+
Description: The person's score
|
96
|
+
Example: 0.0
|
97
|
+
DESCRIPTION
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context "with datetime field type" do
|
102
|
+
before do
|
103
|
+
task_class.output_schema do
|
104
|
+
datetime :created_at, description: "When the person was created"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
it "formats datetime field description correctly" do
|
109
|
+
expect(model.format_prompt(task)).to include(<<~DESCRIPTION.chomp)
|
110
|
+
# created_at
|
111
|
+
Type: datetime in ISO8601 format
|
112
|
+
Description: When the person was created
|
113
|
+
Example: 2024-01-01T12:00:00+00:00
|
114
|
+
DESCRIPTION
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context "with array fields" do
|
120
|
+
context "with simple array of strings" do
|
121
|
+
before do
|
122
|
+
task_class.output_schema do
|
123
|
+
array :tags, description: "List of tags" do
|
124
|
+
string
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
it "formats array of strings field description correctly" do
|
130
|
+
expect(model.format_prompt(task)).to include(<<~DESCRIPTION.chomp)
|
131
|
+
# tags
|
132
|
+
Type: array of string
|
133
|
+
Description: List of tags
|
134
|
+
Example: ["first tag", "second tag", "..."]
|
135
|
+
DESCRIPTION
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
context "with array of floats" do
|
140
|
+
before do
|
141
|
+
task_class.output_schema do
|
142
|
+
array :scores, description: "List of scores" do
|
143
|
+
float
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
it "formats array of floats field description correctly" do
|
149
|
+
expect(model.format_prompt(task)).to include(<<~DESCRIPTION.chomp)
|
150
|
+
# scores
|
151
|
+
Type: array of float
|
152
|
+
Description: List of scores
|
153
|
+
Example: [1.0, 2.0, 3.0]
|
154
|
+
DESCRIPTION
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
context "with array of datetimes" do
|
159
|
+
before do
|
160
|
+
task_class.output_schema do
|
161
|
+
array :dates, description: "List of important dates" do
|
162
|
+
datetime
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
it "formats array of datetimes field description correctly" do
|
168
|
+
expect(model.format_prompt(task)).to include(<<~DESCRIPTION.chomp)
|
169
|
+
# dates
|
170
|
+
Type: array of datetime in ISO8601 format
|
171
|
+
Description: List of important dates
|
172
|
+
Example: ["2024-01-01T12:00:00+00:00", "2024-01-02T12:00:00+00:00"]
|
173
|
+
DESCRIPTION
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
context "with 2D array (matrix)" do
|
178
|
+
before do
|
179
|
+
task_class.output_schema do
|
180
|
+
array :matrix, description: "2D array of numbers" do
|
181
|
+
array { integer }
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
it "formats 2D array field description correctly" do
|
187
|
+
expect(model.format_prompt(task)).to include(<<~DESCRIPTION.chomp)
|
188
|
+
# matrix
|
189
|
+
Type: array of array of integer
|
190
|
+
Description: 2D array of numbers
|
191
|
+
Example: [[1, 2, 3], [1, 2, 3]]
|
192
|
+
DESCRIPTION
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
context "with 3D array (cube)" do
|
197
|
+
before do
|
198
|
+
task_class.output_schema do
|
199
|
+
array :cube, description: "3D array of strings" do
|
200
|
+
array { array { string } }
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
it "formats 3D array field description correctly" do
|
206
|
+
expect(model.format_prompt(task)).to include(<<~DESCRIPTION.chomp)
|
207
|
+
# cube
|
208
|
+
Type: array of array of array of string
|
209
|
+
Description: 3D array of strings
|
210
|
+
Example: [[["first item", "second item", "..."], ["first item", "second item", "..."]], [["first item", "second item", "..."], ["first item", "second item", "..."]]]
|
211
|
+
DESCRIPTION
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
context "with validations" do
|
217
|
+
context "presence validation" do
|
218
|
+
before do
|
219
|
+
task_class.output_schema do
|
220
|
+
string :name, description: "The person's name"
|
221
|
+
validates :name, presence: true
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
it "includes presence validation in field description" do
|
226
|
+
expect(model.format_prompt(task)).to include(<<~DESCRIPTION.chomp)
|
227
|
+
# name
|
228
|
+
Type: string
|
229
|
+
Description: The person's name
|
230
|
+
Validations: must be present
|
231
|
+
Example: your name here
|
232
|
+
DESCRIPTION
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
context "inclusion validation" do
|
237
|
+
before do
|
238
|
+
task_class.output_schema do
|
239
|
+
string :status, description: "The status"
|
240
|
+
validates :status, inclusion: { in: %w[active inactive] }
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
it "includes inclusion validation in field description" do
|
245
|
+
expect(model.format_prompt(task)).to include(<<~DESCRIPTION.chomp)
|
246
|
+
# status
|
247
|
+
Type: string
|
248
|
+
Description: The status
|
249
|
+
Validations: must be one of: active, inactive
|
250
|
+
Example: your status here
|
251
|
+
DESCRIPTION
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
context "exclusion validation" do
|
256
|
+
before do
|
257
|
+
task_class.output_schema do
|
258
|
+
string :status, description: "The status"
|
259
|
+
validates :status, exclusion: { in: %w[banned blocked] }
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
it "includes exclusion validation in field description" do
|
264
|
+
expect(model.format_prompt(task)).to include(<<~DESCRIPTION.chomp)
|
265
|
+
# status
|
266
|
+
Type: string
|
267
|
+
Description: The status
|
268
|
+
Validations: must not be one of: banned, blocked
|
269
|
+
Example: your status here
|
270
|
+
DESCRIPTION
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
context "format validation" do
|
275
|
+
before do
|
276
|
+
task_class.output_schema do
|
277
|
+
string :email, description: "Email address"
|
278
|
+
validates :email, format: { with: /\A[^@\s]+@[^@\s]+\z/ }
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
it "includes format validation in field description" do
|
283
|
+
expect(model.format_prompt(task)).to include(<<~DESCRIPTION.chomp)
|
284
|
+
# email
|
285
|
+
Type: string
|
286
|
+
Description: Email address
|
287
|
+
Validations: must match format: (?-mix:\\A[^@\\s]+@[^@\\s]+\\z)
|
288
|
+
Example: your email here
|
289
|
+
DESCRIPTION
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
context "length validation" do
|
294
|
+
before do
|
295
|
+
task_class.output_schema do
|
296
|
+
string :password, description: "The password"
|
297
|
+
validates :password, length: { minimum: 8, maximum: 20 }
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
it "includes length validation in field description" do
|
302
|
+
expect(model.format_prompt(task)).to include(<<~DESCRIPTION.chomp)
|
303
|
+
# password
|
304
|
+
Type: string
|
305
|
+
Description: The password
|
306
|
+
Validations: must be at least 8 characters, must be at most 20 characters
|
307
|
+
Example: your password here
|
308
|
+
DESCRIPTION
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
context "numericality validation" do
|
313
|
+
before do
|
314
|
+
task_class.output_schema do
|
315
|
+
integer :age, description: "The age"
|
316
|
+
validates :age,
|
317
|
+
numericality: {
|
318
|
+
greater_than: 0,
|
319
|
+
less_than_or_equal_to: 120
|
320
|
+
}
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
it "includes numericality validation in field description" do
|
325
|
+
expect(model.format_prompt(task)).to include(<<~DESCRIPTION.chomp)
|
326
|
+
# age
|
327
|
+
Type: integer
|
328
|
+
Description: The age
|
329
|
+
Validations: must be greater than 0, must be less than or equal to 120
|
330
|
+
Example: 0
|
331
|
+
DESCRIPTION
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
context "multiple validations" do
|
336
|
+
before do
|
337
|
+
task_class.output_schema do
|
338
|
+
string :username, description: "The username"
|
339
|
+
validates :username,
|
340
|
+
presence: true,
|
341
|
+
length: {
|
342
|
+
in: 3..20
|
343
|
+
},
|
344
|
+
format: {
|
345
|
+
with: /\A[a-z0-9_]+\z/
|
346
|
+
}
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
350
|
+
it "includes all validations in field description" do
|
351
|
+
expect(model.format_prompt(task)).to include(<<~DESCRIPTION.chomp)
|
352
|
+
# username
|
353
|
+
Type: string
|
354
|
+
Description: The username
|
355
|
+
Validations: must be present, must be between 3 and 20 characters, must match format: (?-mix:\\A[a-z0-9_]+\\z)
|
356
|
+
Example: your username here
|
357
|
+
DESCRIPTION
|
358
|
+
end
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
context "JSON example generation" do
|
363
|
+
context "with simple field types" do
|
364
|
+
it "generates correct JSON example for string field" do
|
365
|
+
task_class.output_schema do
|
366
|
+
string :name, description: "The person's name"
|
367
|
+
end
|
368
|
+
|
369
|
+
expect(model.format_prompt(task)).to include(<<~JSON.chomp)
|
370
|
+
{
|
371
|
+
"name": "your name here"
|
372
|
+
}
|
373
|
+
JSON
|
374
|
+
end
|
375
|
+
|
376
|
+
it "generates correct JSON example for integer field" do
|
377
|
+
task_class.output_schema do
|
378
|
+
integer :age, description: "The person's age"
|
379
|
+
end
|
380
|
+
|
381
|
+
expect(model.format_prompt(task)).to include(<<~JSON.chomp)
|
382
|
+
{
|
383
|
+
"age": 0
|
384
|
+
}
|
385
|
+
JSON
|
386
|
+
end
|
387
|
+
|
388
|
+
it "generates correct JSON example for boolean field" do
|
389
|
+
task_class.output_schema do
|
390
|
+
boolean :is_active, description: "Whether the person is active"
|
391
|
+
end
|
392
|
+
|
393
|
+
expect(model.format_prompt(task)).to include(<<~JSON.chomp)
|
394
|
+
{
|
395
|
+
"is_active": true
|
396
|
+
}
|
397
|
+
JSON
|
398
|
+
end
|
399
|
+
|
400
|
+
it "generates correct JSON example for float field" do
|
401
|
+
task_class.output_schema { float :score, description: "The score" }
|
402
|
+
|
403
|
+
expect(model.format_prompt(task)).to include(<<~JSON.chomp)
|
404
|
+
{
|
405
|
+
"score": 0.0
|
406
|
+
}
|
407
|
+
JSON
|
408
|
+
end
|
409
|
+
|
410
|
+
it "generates correct JSON example for datetime field" do
|
411
|
+
task_class.output_schema do
|
412
|
+
datetime :created_at, description: "When it was created"
|
413
|
+
end
|
414
|
+
|
415
|
+
expect(model.format_prompt(task)).to include(<<~JSON.chomp)
|
416
|
+
{
|
417
|
+
"created_at": "2024-01-01T12:00:00+00:00"
|
418
|
+
}
|
419
|
+
JSON
|
420
|
+
end
|
421
|
+
end
|
422
|
+
|
423
|
+
context "with array fields" do
|
424
|
+
it "generates correct JSON example for array of strings" do
|
425
|
+
task_class.output_schema do
|
426
|
+
array :tags, description: "List of tags" do
|
427
|
+
string
|
428
|
+
end
|
429
|
+
end
|
430
|
+
|
431
|
+
expect(model.format_prompt(task)).to include(<<~JSON.chomp)
|
432
|
+
{
|
433
|
+
"tags": [
|
434
|
+
"first tag",
|
435
|
+
"second tag",
|
436
|
+
"..."
|
437
|
+
]
|
438
|
+
}
|
439
|
+
JSON
|
440
|
+
end
|
441
|
+
|
442
|
+
it "generates correct JSON example for array of integers" do
|
443
|
+
task_class.output_schema do
|
444
|
+
array :counts, description: "List of counts" do
|
445
|
+
integer
|
446
|
+
end
|
447
|
+
end
|
448
|
+
|
449
|
+
expect(model.format_prompt(task)).to include(<<~JSON.chomp)
|
450
|
+
{
|
451
|
+
"counts": [
|
452
|
+
1,
|
453
|
+
2,
|
454
|
+
3
|
455
|
+
]
|
456
|
+
}
|
457
|
+
JSON
|
458
|
+
end
|
459
|
+
|
460
|
+
it "generates correct JSON example for array of datetimes" do
|
461
|
+
task_class.output_schema do
|
462
|
+
array :timestamps, description: "List of timestamps" do
|
463
|
+
datetime
|
464
|
+
end
|
465
|
+
end
|
466
|
+
|
467
|
+
expect(model.format_prompt(task)).to include(<<~JSON.chomp)
|
468
|
+
{
|
469
|
+
"timestamps": [
|
470
|
+
"2024-01-01T12:00:00+00:00",
|
471
|
+
"2024-01-02T12:00:00+00:00"
|
472
|
+
]
|
473
|
+
}
|
474
|
+
JSON
|
475
|
+
end
|
476
|
+
|
477
|
+
it "generates correct JSON example for array without element type" do
|
478
|
+
task_class.output_schema do
|
479
|
+
array :items, description: "List of items"
|
480
|
+
end
|
481
|
+
|
482
|
+
expect(model.format_prompt(task)).to include(<<~JSON.chomp)
|
483
|
+
{
|
484
|
+
"items": []
|
485
|
+
}
|
486
|
+
JSON
|
487
|
+
end
|
488
|
+
|
489
|
+
it "generates correct JSON example for nested array of strings" do
|
490
|
+
task_class.output_schema do
|
491
|
+
array :groups, description: "Groups of items" do
|
492
|
+
array { string }
|
493
|
+
end
|
494
|
+
end
|
495
|
+
|
496
|
+
expect(model.format_prompt(task)).to include(<<~JSON.chomp)
|
497
|
+
{
|
498
|
+
"groups": [
|
499
|
+
[
|
500
|
+
"first item",
|
501
|
+
"second item",
|
502
|
+
"..."
|
503
|
+
],
|
504
|
+
[
|
505
|
+
"first item",
|
506
|
+
"second item",
|
507
|
+
"..."
|
508
|
+
]
|
509
|
+
]
|
510
|
+
}
|
511
|
+
JSON
|
512
|
+
end
|
513
|
+
|
514
|
+
it "generates correct JSON example for three-dimensional array of integers" do
|
515
|
+
task_class.output_schema do
|
516
|
+
array :matrices, description: "Collection of matrices" do
|
517
|
+
array { array { integer } }
|
518
|
+
end
|
519
|
+
end
|
520
|
+
|
521
|
+
expect(model.format_prompt(task)).to include(<<~JSON.chomp)
|
522
|
+
{
|
523
|
+
"matrices": [
|
524
|
+
[
|
525
|
+
[
|
526
|
+
1,
|
527
|
+
2,
|
528
|
+
3
|
529
|
+
],
|
530
|
+
[
|
531
|
+
1,
|
532
|
+
2,
|
533
|
+
3
|
534
|
+
]
|
535
|
+
],
|
536
|
+
[
|
537
|
+
[
|
538
|
+
1,
|
539
|
+
2,
|
540
|
+
3
|
541
|
+
],
|
542
|
+
[
|
543
|
+
1,
|
544
|
+
2,
|
545
|
+
3
|
546
|
+
]
|
547
|
+
]
|
548
|
+
]
|
549
|
+
}
|
550
|
+
JSON
|
551
|
+
end
|
552
|
+
end
|
553
|
+
|
554
|
+
context "with multiple fields" do
|
555
|
+
it "generates correct JSON example for mixed field types" do
|
556
|
+
task_class.output_schema do
|
557
|
+
string :name, description: "The person's name"
|
558
|
+
integer :age, description: "The person's age"
|
559
|
+
array :hobbies, description: "List of hobbies" do
|
560
|
+
string
|
561
|
+
end
|
562
|
+
datetime :joined_at, description: "When they joined"
|
563
|
+
end
|
564
|
+
|
565
|
+
expect(model.format_prompt(task)).to include(<<~JSON.chomp)
|
566
|
+
{
|
567
|
+
"name": "your name here",
|
568
|
+
"age": 0,
|
569
|
+
"hobbies": [
|
570
|
+
"first hobby",
|
571
|
+
"second hobby",
|
572
|
+
"..."
|
573
|
+
],
|
574
|
+
"joined_at": "2024-01-01T12:00:00+00:00"
|
575
|
+
}
|
576
|
+
JSON
|
577
|
+
end
|
578
|
+
end
|
579
|
+
end
|
580
|
+
end
|
581
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
require "lluminary/models/bedrock/amazon_nova_pro_v1"
|
5
|
+
|
6
|
+
RSpec.describe Lluminary::Models::Bedrock::AmazonNovaProV1 do
|
7
|
+
let(:model) { described_class.new }
|
8
|
+
|
9
|
+
describe "NAME" do
|
10
|
+
it "has the correct model name" do
|
11
|
+
expect(described_class::NAME).to eq("amazon.nova-pro-v1")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#compatible_with?" do
|
16
|
+
it "returns true for bedrock provider" do
|
17
|
+
expect(model.compatible_with?(:bedrock)).to be true
|
18
|
+
end
|
19
|
+
|
20
|
+
it "returns false for other providers" do
|
21
|
+
expect(model.compatible_with?(:openai)).to be false
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#name" do
|
26
|
+
it "returns the model name" do
|
27
|
+
expect(model.name).to eq("amazon.nova-pro-v1:0")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
RSpec.describe Lluminary::Models::Bedrock::AnthropicClaudeInstantV1 do
|
4
|
+
subject(:model) { described_class.new }
|
5
|
+
|
6
|
+
describe "#NAME" do
|
7
|
+
it "returns the correct model name" do
|
8
|
+
expect(described_class::NAME).to eq("anthropic.claude-instant-v1")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#compatible_with?" do
|
13
|
+
it "returns true for :bedrock provider" do
|
14
|
+
expect(model.compatible_with?(:bedrock)).to be true
|
15
|
+
end
|
16
|
+
|
17
|
+
it "returns false for other providers" do
|
18
|
+
expect(model.compatible_with?(:openai)).to be false
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "spec_helper"
|
3
|
+
|
4
|
+
RSpec.describe Lluminary::Models::OpenAi::Gpt35Turbo do
|
5
|
+
subject(:model) { described_class.new }
|
6
|
+
|
7
|
+
describe "#NAME" do
|
8
|
+
it "returns the correct model name" do
|
9
|
+
expect(described_class::NAME).to eq("gpt-3.5-turbo")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#compatible_with?" do
|
14
|
+
it "returns true for :openai provider" do
|
15
|
+
expect(model.compatible_with?(:openai)).to be true
|
16
|
+
end
|
17
|
+
|
18
|
+
it "returns false for other providers" do
|
19
|
+
expect(model.compatible_with?(:bedrock)).to be false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -18,6 +18,45 @@ RSpec.describe Lluminary::Providers::Bedrock do
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
+
describe "#models" do
|
22
|
+
let(:mock_models_response) do
|
23
|
+
OpenStruct.new(
|
24
|
+
foundation_models: [
|
25
|
+
OpenStruct.new(
|
26
|
+
model_id: "anthropic.claude-instant-v1",
|
27
|
+
model_name: "Claude Instant",
|
28
|
+
provider_name: "Anthropic",
|
29
|
+
input_modalities: ["TEXT"],
|
30
|
+
output_modalities: ["TEXT"],
|
31
|
+
customizations_supported: []
|
32
|
+
),
|
33
|
+
OpenStruct.new(
|
34
|
+
model_id: "anthropic.claude-v2",
|
35
|
+
model_name: "Claude V2",
|
36
|
+
provider_name: "Anthropic",
|
37
|
+
input_modalities: ["TEXT"],
|
38
|
+
output_modalities: ["TEXT"],
|
39
|
+
customizations_supported: []
|
40
|
+
)
|
41
|
+
]
|
42
|
+
)
|
43
|
+
end
|
44
|
+
|
45
|
+
before do
|
46
|
+
models_client = double("BedrockClient")
|
47
|
+
allow(Aws::Bedrock::Client).to receive(:new).and_return(models_client)
|
48
|
+
allow(models_client).to receive(:list_foundation_models).and_return(
|
49
|
+
mock_models_response
|
50
|
+
)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "returns an array of model IDs as strings" do
|
54
|
+
expect(provider.models).to eq(
|
55
|
+
%w[anthropic.claude-instant-v1 anthropic.claude-v2]
|
56
|
+
)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
21
60
|
describe "#call" do
|
22
61
|
let(:prompt) { "Test prompt" }
|
23
62
|
let(:task) { "Test task" }
|