lluminary 0.1.1 → 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 +6 -1
- 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/provider_error.rb +2 -1
- data/lib/lluminary/providers/base.rb +20 -3
- data/lib/lluminary/providers/bedrock.rb +52 -32
- data/lib/lluminary/providers/openai.rb +41 -24
- data/lib/lluminary/providers/test.rb +14 -13
- data/lib/lluminary/result.rb +5 -2
- data/lib/lluminary/schema.rb +59 -15
- data/lib/lluminary/schema_model.rb +67 -10
- data/lib/lluminary/task.rb +58 -99
- data/lib/lluminary/validation_error.rb +2 -1
- data/lib/lluminary/version.rb +3 -2
- data/lib/lluminary.rb +25 -7
- data/spec/examples/analyze_text_spec.rb +7 -4
- data/spec/examples/color_analyzer_spec.rb +22 -22
- data/spec/examples/content_analyzer_spec.rb +27 -44
- data/spec/examples/historical_event_analyzer_spec.rb +18 -15
- data/spec/examples/meal_suggester_spec.rb +64 -0
- data/spec/examples/price_analyzer_spec.rb +22 -28
- data/spec/examples/quote_task_spec.rb +9 -8
- data/spec/examples/sentiment_analysis_spec.rb +13 -10
- data/spec/examples/summarize_text_spec.rb +7 -4
- data/spec/lluminary/config_spec.rb +28 -26
- 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 +86 -57
- data/spec/lluminary/providers/openai_spec.rb +58 -34
- data/spec/lluminary/providers/test_spec.rb +46 -16
- data/spec/lluminary/result_spec.rb +17 -10
- data/spec/lluminary/schema_model_spec.rb +108 -22
- data/spec/lluminary/schema_spec.rb +241 -107
- data/spec/lluminary/task_spec.rb +118 -584
- data/spec/spec_helper.rb +8 -2
- metadata +73 -22
- data/lib/lluminary/field_description.rb +0 -148
- data/spec/lluminary/field_description_spec.rb +0 -36
- data/spec/lluminary/providers/base_spec.rb +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 77729a2c4dc59717c0fd5c8fa8cf21df682bbaeff5c66e501f0e409cb8ac16c4
|
4
|
+
data.tar.gz: 46aa2188fcad140a7e7dfa2cc3d4bd5008d1bd5afbf70920bc3b211eb9018480
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ed78898c62ab28d52136d470f5ccf398b3d5dcce8643af51348834877b3561ae3ca5b0ca1e7d12fbab6d0a8b677e7599c393dd9f678af970da5d3d5f01da9e24
|
7
|
+
data.tar.gz: 961371925c55006aedfe7b89d043aa10411f90b26fe1c67be356c2b81ebcc618417eb0fa1ff1cdf5dcd7344adb0e75b208d82e0ae256e0497c178c6f6d3569f9
|
data/lib/lluminary/config.rb
CHANGED
@@ -1,4 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Lluminary
|
4
|
+
# Configuration class for Lluminary framework.
|
5
|
+
# Handles global settings and provider configurations.
|
6
|
+
|
2
7
|
class Config
|
3
8
|
def initialize
|
4
9
|
@providers = {}
|
@@ -20,4 +25,4 @@ module Lluminary
|
|
20
25
|
@providers = {}
|
21
26
|
end
|
22
27
|
end
|
23
|
-
end
|
28
|
+
end
|
@@ -0,0 +1,235 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lluminary
|
4
|
+
module Models
|
5
|
+
# Base class for all LLM models.
|
6
|
+
# Defines the interface that all model classes must implement and provides
|
7
|
+
# default prompt formatting behavior.
|
8
|
+
class Base
|
9
|
+
# Checks if this model is compatible with a given provider
|
10
|
+
# @param provider_name [Symbol] The name of the provider to check
|
11
|
+
# @return [Boolean]
|
12
|
+
def compatible_with?(provider_name)
|
13
|
+
raise NotImplementedError, "Subclasses must implement #compatible_with?"
|
14
|
+
end
|
15
|
+
|
16
|
+
# Returns the name of the model
|
17
|
+
# @return [String]
|
18
|
+
def name
|
19
|
+
raise NotImplementedError, "Subclasses must implement #name"
|
20
|
+
end
|
21
|
+
|
22
|
+
def format_prompt(task)
|
23
|
+
<<~PROMPT
|
24
|
+
#{task.task_prompt.chomp}
|
25
|
+
|
26
|
+
#{output_preamble}
|
27
|
+
|
28
|
+
#{format_field_descriptions(task.class.output_fields)}
|
29
|
+
|
30
|
+
#{json_preamble}
|
31
|
+
|
32
|
+
#{format_json_example(task.class.output_fields)}
|
33
|
+
PROMPT
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def output_preamble
|
39
|
+
<<~PREAMBLE.chomp
|
40
|
+
You must respond with ONLY a valid JSON object. Do not include any other text, explanations, or formatting.
|
41
|
+
The JSON object must contain the following fields:
|
42
|
+
PREAMBLE
|
43
|
+
end
|
44
|
+
|
45
|
+
def json_preamble
|
46
|
+
"Your response must be ONLY this JSON object:"
|
47
|
+
end
|
48
|
+
|
49
|
+
def format_field_descriptions(fields)
|
50
|
+
fields
|
51
|
+
.map do |name, field|
|
52
|
+
desc = "# #{name}"
|
53
|
+
desc += "\nType: #{format_type(field)}"
|
54
|
+
|
55
|
+
desc += "\nDescription: #{field[:description].chomp}" if field[
|
56
|
+
:description
|
57
|
+
]
|
58
|
+
|
59
|
+
if (validations = describe_validations(field[:validations]))
|
60
|
+
desc += "\nValidations: #{validations}"
|
61
|
+
end
|
62
|
+
|
63
|
+
desc += "\nExample: #{generate_example_value(name, field)}"
|
64
|
+
desc
|
65
|
+
end
|
66
|
+
.join("\n\n")
|
67
|
+
end
|
68
|
+
|
69
|
+
def describe_validations(validations)
|
70
|
+
return unless validations&.any?
|
71
|
+
|
72
|
+
validations
|
73
|
+
.map do |options|
|
74
|
+
case options.keys.first
|
75
|
+
when :presence
|
76
|
+
"must be present"
|
77
|
+
when :inclusion
|
78
|
+
"must be one of: #{options[:inclusion][:in].join(", ")}"
|
79
|
+
when :exclusion
|
80
|
+
"must not be one of: #{options[:exclusion][:in].join(", ")}"
|
81
|
+
when :format
|
82
|
+
"must match format: #{options[:format][:with]}"
|
83
|
+
when :length
|
84
|
+
describe_length_validation(options[:length])
|
85
|
+
when :numericality
|
86
|
+
describe_numericality_validation(options[:numericality])
|
87
|
+
when :comparison
|
88
|
+
describe_comparison_validation(options[:comparison])
|
89
|
+
when :absence
|
90
|
+
"must be absent"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
.compact
|
94
|
+
.join(", ")
|
95
|
+
end
|
96
|
+
|
97
|
+
def describe_length_validation(options)
|
98
|
+
descriptions = []
|
99
|
+
if options[:minimum]
|
100
|
+
descriptions << "must be at least #{options[:minimum]} characters"
|
101
|
+
end
|
102
|
+
if options[:maximum]
|
103
|
+
descriptions << "must be at most #{options[:maximum]} characters"
|
104
|
+
end
|
105
|
+
if options[:is]
|
106
|
+
descriptions << "must be exactly #{options[:is]} characters"
|
107
|
+
end
|
108
|
+
if options[:in]
|
109
|
+
descriptions << "must be between #{options[:in].min} and #{options[:in].max} characters"
|
110
|
+
end
|
111
|
+
descriptions.join(", ")
|
112
|
+
end
|
113
|
+
|
114
|
+
def describe_numericality_validation(options)
|
115
|
+
descriptions = []
|
116
|
+
if options[:greater_than]
|
117
|
+
descriptions << "must be greater than #{options[:greater_than]}"
|
118
|
+
end
|
119
|
+
if options[:greater_than_or_equal_to]
|
120
|
+
descriptions << "must be greater than or equal to #{options[:greater_than_or_equal_to]}"
|
121
|
+
end
|
122
|
+
if options[:equal_to]
|
123
|
+
descriptions << "must be equal to #{options[:equal_to]}"
|
124
|
+
end
|
125
|
+
if options[:less_than]
|
126
|
+
descriptions << "must be less than #{options[:less_than]}"
|
127
|
+
end
|
128
|
+
if options[:less_than_or_equal_to]
|
129
|
+
descriptions << "must be less than or equal to #{options[:less_than_or_equal_to]}"
|
130
|
+
end
|
131
|
+
if options[:other_than]
|
132
|
+
descriptions << "must be other than #{options[:other_than]}"
|
133
|
+
end
|
134
|
+
if options[:in]
|
135
|
+
descriptions << "must be in: #{options[:in].to_a.join(", ")}"
|
136
|
+
end
|
137
|
+
descriptions << "must be odd" if options[:odd]
|
138
|
+
descriptions << "must be even" if options[:even]
|
139
|
+
descriptions.join(", ")
|
140
|
+
end
|
141
|
+
|
142
|
+
def describe_comparison_validation(options)
|
143
|
+
descriptions = []
|
144
|
+
if options[:greater_than]
|
145
|
+
descriptions << "must be greater than #{options[:greater_than]}"
|
146
|
+
end
|
147
|
+
if options[:greater_than_or_equal_to]
|
148
|
+
descriptions << "must be greater than or equal to #{options[:greater_than_or_equal_to]}"
|
149
|
+
end
|
150
|
+
if options[:equal_to]
|
151
|
+
descriptions << "must be equal to #{options[:equal_to]}"
|
152
|
+
end
|
153
|
+
if options[:less_than]
|
154
|
+
descriptions << "must be less than #{options[:less_than]}"
|
155
|
+
end
|
156
|
+
if options[:less_than_or_equal_to]
|
157
|
+
descriptions << "must be less than or equal to #{options[:less_than_or_equal_to]}"
|
158
|
+
end
|
159
|
+
if options[:other_than]
|
160
|
+
descriptions << "must be other than #{options[:other_than]}"
|
161
|
+
end
|
162
|
+
descriptions.join(", ")
|
163
|
+
end
|
164
|
+
|
165
|
+
def format_json_example(fields)
|
166
|
+
example =
|
167
|
+
fields.each_with_object({}) do |(name, field), hash|
|
168
|
+
hash[name] = generate_example_value(name, field)
|
169
|
+
end
|
170
|
+
JSON.pretty_generate(example)
|
171
|
+
end
|
172
|
+
|
173
|
+
def format_type(field)
|
174
|
+
type = field[:type]
|
175
|
+
case type
|
176
|
+
when :datetime
|
177
|
+
"datetime in ISO8601 format"
|
178
|
+
when :array
|
179
|
+
if field[:element_type]
|
180
|
+
"array of #{format_type(field[:element_type])}"
|
181
|
+
else
|
182
|
+
"array"
|
183
|
+
end
|
184
|
+
else
|
185
|
+
type.to_s
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
def generate_example_value(name, field)
|
190
|
+
case field[:type]
|
191
|
+
when :string
|
192
|
+
"your #{name} here"
|
193
|
+
when :integer
|
194
|
+
0
|
195
|
+
when :datetime
|
196
|
+
"2024-01-01T12:00:00+00:00"
|
197
|
+
when :boolean
|
198
|
+
true
|
199
|
+
when :float
|
200
|
+
0.0
|
201
|
+
when :array
|
202
|
+
generate_array_example(name, field)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
def generate_array_example(name, field)
|
207
|
+
return [] unless field[:element_type]
|
208
|
+
|
209
|
+
case field[:element_type][:type]
|
210
|
+
when :string
|
211
|
+
[
|
212
|
+
"first #{name.to_s.singularize}",
|
213
|
+
"second #{name.to_s.singularize}",
|
214
|
+
"..."
|
215
|
+
]
|
216
|
+
when :integer
|
217
|
+
[1, 2, 3]
|
218
|
+
when :float
|
219
|
+
[1.0, 2.0, 3.0]
|
220
|
+
when :boolean
|
221
|
+
[true, false, true]
|
222
|
+
when :datetime
|
223
|
+
%w[2024-01-01T12:00:00+00:00 2024-01-02T12:00:00+00:00]
|
224
|
+
when :array
|
225
|
+
if field[:element_type][:element_type]
|
226
|
+
inner_example = generate_array_example("item", field[:element_type])
|
227
|
+
[inner_example, inner_example]
|
228
|
+
else
|
229
|
+
[["..."], ["..."]]
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "base"
|
4
|
+
|
5
|
+
module Lluminary
|
6
|
+
module Models
|
7
|
+
module Bedrock
|
8
|
+
class AmazonNovaProV1 < Lluminary::Models::Bedrock::Base
|
9
|
+
NAME = "amazon.nova-pro-v1"
|
10
|
+
VERSIONS = %w[0].freeze
|
11
|
+
CONTEXT_WINDOWS = %w[24k 300k].freeze
|
12
|
+
|
13
|
+
def compatible_with?(provider_name)
|
14
|
+
provider_name == :bedrock
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "base"
|
4
|
+
|
5
|
+
module Lluminary
|
6
|
+
module Models
|
7
|
+
module Bedrock
|
8
|
+
class AnthropicClaudeInstantV1 < Lluminary::Models::Bedrock::Base
|
9
|
+
NAME = "anthropic.claude-instant-v1"
|
10
|
+
|
11
|
+
def compatible_with?(provider_name)
|
12
|
+
provider_name == :bedrock
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lluminary
|
4
|
+
module Models
|
5
|
+
module Bedrock
|
6
|
+
# TODO: test me
|
7
|
+
class Base < Lluminary::Models::Base
|
8
|
+
VERSIONS = [].freeze
|
9
|
+
CONTEXT_WINDOWS = [].freeze
|
10
|
+
|
11
|
+
def default_version
|
12
|
+
self.class::VERSIONS.last
|
13
|
+
end
|
14
|
+
|
15
|
+
def default_context_window
|
16
|
+
nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def name
|
20
|
+
[
|
21
|
+
self.class::NAME,
|
22
|
+
default_version,
|
23
|
+
default_context_window
|
24
|
+
].compact.join(":")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Lluminary
|
4
|
+
module Models
|
5
|
+
module OpenAi
|
6
|
+
# Model class for OpenAI's GPT-3.5 Turbo
|
7
|
+
class Gpt35Turbo < Base
|
8
|
+
NAME = "gpt-3.5-turbo"
|
9
|
+
|
10
|
+
def compatible_with?(provider_name)
|
11
|
+
provider_name == :openai
|
12
|
+
end
|
13
|
+
|
14
|
+
def name
|
15
|
+
NAME
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -1,15 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Lluminary
|
2
4
|
module Providers
|
5
|
+
# Base class for all LLM providers.
|
6
|
+
# Defines the interface that all providers must implement.
|
3
7
|
class Base
|
8
|
+
# The symbolic name of the provider. Must be overridden by subclasses.
|
9
|
+
NAME = :base
|
10
|
+
|
4
11
|
attr_reader :config
|
5
12
|
|
6
|
-
def initialize(**
|
7
|
-
@config =
|
13
|
+
def initialize(**config_overrides)
|
14
|
+
@config = default_provider_config.merge(config_overrides)
|
8
15
|
end
|
9
16
|
|
10
17
|
def call(prompt, task)
|
11
18
|
raise NotImplementedError, "Subclasses must implement #call"
|
12
19
|
end
|
20
|
+
|
21
|
+
def models
|
22
|
+
raise NotImplementedError, "Subclasses must implement #models"
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def default_provider_config
|
28
|
+
Lluminary.config.provider_config(self.class::NAME)
|
29
|
+
end
|
13
30
|
end
|
14
31
|
end
|
15
|
-
end
|
32
|
+
end
|
@@ -1,51 +1,71 @@
|
|
1
|
-
|
2
|
-
require
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "aws-sdk-bedrockruntime"
|
3
|
+
require "aws-sdk-bedrock"
|
4
|
+
require "json"
|
5
|
+
require_relative "../provider_error"
|
6
6
|
|
7
7
|
module Lluminary
|
8
8
|
module Providers
|
9
|
+
# Provider for AWS Bedrock models.
|
10
|
+
# Implements the Base provider interface for AWS Bedrock's API.
|
9
11
|
class Bedrock < Base
|
10
|
-
|
12
|
+
NAME = :bedrock
|
13
|
+
DEFAULT_MODEL = Models::Bedrock::AnthropicClaudeInstantV1
|
11
14
|
|
12
15
|
attr_reader :client, :config
|
13
16
|
|
14
|
-
def initialize(**
|
17
|
+
def initialize(**config_overrides)
|
15
18
|
super
|
16
|
-
@config = config
|
19
|
+
@config = { model: DEFAULT_MODEL }.merge(config)
|
17
20
|
|
18
|
-
@client =
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
21
|
+
@client =
|
22
|
+
Aws::BedrockRuntime::Client.new(
|
23
|
+
region: config[:region],
|
24
|
+
credentials:
|
25
|
+
Aws::Credentials.new(
|
26
|
+
config[:access_key_id],
|
27
|
+
config[:secret_access_key]
|
28
|
+
)
|
23
29
|
)
|
24
|
-
)
|
25
30
|
end
|
26
31
|
|
27
|
-
def call(prompt,
|
28
|
-
response =
|
29
|
-
|
30
|
-
|
31
|
-
{
|
32
|
-
|
33
|
-
content: [{text: prompt}]
|
34
|
-
}
|
35
|
-
]
|
36
|
-
)
|
32
|
+
def call(prompt, _task)
|
33
|
+
response =
|
34
|
+
client.converse(
|
35
|
+
model_id: model.name,
|
36
|
+
messages: [{ role: "user", content: [{ text: prompt }] }]
|
37
|
+
)
|
37
38
|
|
38
39
|
content = response.dig(:output, :message, :content, 0, :text)
|
39
|
-
|
40
|
-
{
|
40
|
+
|
41
|
+
{
|
41
42
|
raw: content,
|
42
|
-
parsed:
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
43
|
+
parsed:
|
44
|
+
begin
|
45
|
+
JSON.parse(content) if content
|
46
|
+
rescue JSON::ParserError
|
47
|
+
nil
|
48
|
+
end
|
47
49
|
}
|
48
50
|
end
|
51
|
+
|
52
|
+
def model
|
53
|
+
@model ||= config[:model].new
|
54
|
+
end
|
55
|
+
|
56
|
+
def models
|
57
|
+
models_client =
|
58
|
+
Aws::Bedrock::Client.new(
|
59
|
+
region: config[:region],
|
60
|
+
credentials:
|
61
|
+
Aws::Credentials.new(
|
62
|
+
config[:access_key_id],
|
63
|
+
config[:secret_access_key]
|
64
|
+
)
|
65
|
+
)
|
66
|
+
response = models_client.list_foundation_models
|
67
|
+
response.foundation_models.map(&:model_id)
|
68
|
+
end
|
49
69
|
end
|
50
70
|
end
|
51
|
-
end
|
71
|
+
end
|
@@ -1,40 +1,57 @@
|
|
1
|
-
|
2
|
-
require
|
3
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "openai"
|
3
|
+
require "json"
|
4
|
+
require_relative "../provider_error"
|
4
5
|
|
5
6
|
module Lluminary
|
6
7
|
module Providers
|
8
|
+
# Provider for OpenAI's GPT models.
|
9
|
+
# Implements the Base provider interface for OpenAI's API.
|
7
10
|
class OpenAI < Base
|
8
|
-
|
11
|
+
NAME = :openai
|
12
|
+
DEFAULT_MODEL = Models::OpenAi::Gpt35Turbo
|
9
13
|
|
10
14
|
attr_reader :client, :config
|
11
15
|
|
12
|
-
def initialize(**
|
16
|
+
def initialize(**config_overrides)
|
13
17
|
super
|
14
|
-
@config = config
|
18
|
+
@config = { model: DEFAULT_MODEL }.merge(config)
|
15
19
|
@client = ::OpenAI::Client.new(access_token: config[:api_key])
|
16
20
|
end
|
17
21
|
|
18
|
-
def call(prompt,
|
19
|
-
response =
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
22
|
+
def call(prompt, _task)
|
23
|
+
response =
|
24
|
+
client.chat(
|
25
|
+
parameters: {
|
26
|
+
model: model.class::NAME,
|
27
|
+
messages: [{ role: "user", content: prompt }],
|
28
|
+
response_format: {
|
29
|
+
type: "json_object"
|
30
|
+
}
|
31
|
+
}
|
32
|
+
)
|
33
|
+
|
34
|
+
content = response.dig("choices", 0, "message", "content")
|
35
|
+
|
36
|
+
{
|
30
37
|
raw: content,
|
31
|
-
parsed:
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
38
|
+
parsed:
|
39
|
+
begin
|
40
|
+
JSON.parse(content) if content
|
41
|
+
rescue JSON::ParserError
|
42
|
+
nil
|
43
|
+
end
|
36
44
|
}
|
37
45
|
end
|
46
|
+
|
47
|
+
def model
|
48
|
+
@model ||= config[:model].new
|
49
|
+
end
|
50
|
+
|
51
|
+
def models
|
52
|
+
response = @client.models.list
|
53
|
+
response["data"].map { |model| model["id"] }
|
54
|
+
end
|
38
55
|
end
|
39
56
|
end
|
40
|
-
end
|
57
|
+
end
|
@@ -1,25 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Lluminary
|
2
4
|
module Providers
|
5
|
+
# Test provider for development and testing.
|
6
|
+
# Returns predefined responses for testing purposes.
|
3
7
|
class Test < Base
|
4
|
-
|
5
|
-
super
|
6
|
-
end
|
8
|
+
NAME = :test
|
7
9
|
|
8
|
-
def call(
|
10
|
+
def call(_prompt, task)
|
9
11
|
response = generate_response(task.class.output_fields)
|
10
|
-
raw_response = JSON.pretty_generate(response).gsub(/\n\s*/,
|
11
|
-
{
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
raw_response = JSON.pretty_generate(response).gsub(/\n\s*/, "")
|
13
|
+
{ raw: raw_response, parsed: JSON.parse(raw_response) }
|
14
|
+
end
|
15
|
+
|
16
|
+
def model
|
17
|
+
@model ||= Lluminary::Models::Base.new
|
15
18
|
end
|
16
19
|
|
17
20
|
private
|
18
21
|
|
19
22
|
def generate_response(fields)
|
20
|
-
fields.
|
21
|
-
hash[name] = generate_value(field[:type])
|
22
|
-
end
|
23
|
+
fields.transform_values { |field| generate_value(field[:type]) }
|
23
24
|
end
|
24
25
|
|
25
26
|
def generate_value(type)
|
@@ -34,4 +35,4 @@ module Lluminary
|
|
34
35
|
end
|
35
36
|
end
|
36
37
|
end
|
37
|
-
end
|
38
|
+
end
|
data/lib/lluminary/result.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "ostruct"
|
2
3
|
|
3
4
|
module Lluminary
|
5
|
+
# Represents the result of a task execution.
|
6
|
+
# Contains the output data and any metadata about the execution.
|
4
7
|
class Result
|
5
8
|
attr_reader :raw_response, :output, :prompt
|
6
9
|
|
@@ -10,4 +13,4 @@ module Lluminary
|
|
10
13
|
@prompt = prompt
|
11
14
|
end
|
12
15
|
end
|
13
|
-
end
|
16
|
+
end
|