last_llm 0.0.4
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 +7 -0
- data/README.md +246 -0
- data/lib/last_llm/client.rb +100 -0
- data/lib/last_llm/completion.rb +19 -0
- data/lib/last_llm/configuration.rb +115 -0
- data/lib/last_llm/extensions/dry_schema_extensions.rb +76 -0
- data/lib/last_llm/provider.rb +152 -0
- data/lib/last_llm/providers/anthropic.rb +124 -0
- data/lib/last_llm/providers/constants.rb +33 -0
- data/lib/last_llm/providers/deepseek.rb +121 -0
- data/lib/last_llm/providers/google_gemini.rb +175 -0
- data/lib/last_llm/providers/ollama.rb +124 -0
- data/lib/last_llm/providers/openai.rb +184 -0
- data/lib/last_llm/providers/test_provider.rb +38 -0
- data/lib/last_llm/railtie.rb +38 -0
- data/lib/last_llm/schema.rb +241 -0
- data/lib/last_llm/structured_output.rb +58 -0
- data/lib/last_llm/tool.rb +110 -0
- data/lib/last_llm/version.rb +5 -0
- data/lib/last_llm.rb +88 -0
- metadata +144 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d78bc33e36c3ef1607bf80d2c705270be6cbbb52461d5fed514472883362887a
|
4
|
+
data.tar.gz: e9334a1daeac0a22c2f52062607aebd218d84aa99f36660ec3bfe2cecb46cb79
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c51e25832988833bb611154577739ebce7a294e6d2559cc7c0abb77139133baff47054db9fd64dab0e546aaa0448e84d5d1fdd4dbebdefd88474a9933aa84794
|
7
|
+
data.tar.gz: 315701e1f58d1ce6ad780f7a68e3bb254f71f35837e0648d4126285e00e51d1cb50a7eda065e2f60bf2d63cd6a3dfeddf60b739c057b9b1929d7d5bbb66f6893
|
data/README.md
ADDED
@@ -0,0 +1,246 @@
|
|
1
|
+
# LastLLM
|
2
|
+
|
3
|
+
LastLLM is a unified client for interacting with various LLM (Large Language Model) providers. It provides a consistent interface for text generation, structured data generation, and tool calling across different LLM services.
|
4
|
+
|
5
|
+
## Features
|
6
|
+
|
7
|
+
- Unified interface for multiple LLM providers:
|
8
|
+
- OpenAI
|
9
|
+
- Anthropic
|
10
|
+
- Google Gemini
|
11
|
+
- Deepseek
|
12
|
+
- Ollama
|
13
|
+
- Text generation
|
14
|
+
- Structured data generation with schema validation
|
15
|
+
- Tool/function calling support
|
16
|
+
- Rails integration
|
17
|
+
- Configuration management
|
18
|
+
- Error handling
|
19
|
+
|
20
|
+
## Installation
|
21
|
+
|
22
|
+
Add this line to your application's Gemfile:
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
gem 'last_llm'
|
26
|
+
```
|
27
|
+
|
28
|
+
## Configuration
|
29
|
+
|
30
|
+
Configure LastLLM globally or per instance:
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
LastLLM.configure do |config|
|
34
|
+
config.default_provider = :openai
|
35
|
+
config.default_model = 'gpt-3.5-turbo'
|
36
|
+
|
37
|
+
# Configure OpenAI
|
38
|
+
config.configure_provider(:openai, api_key: 'your-api-key')
|
39
|
+
|
40
|
+
# Configure Anthropic
|
41
|
+
config.configure_provider(:anthropic, api_key: 'your-api-key')
|
42
|
+
|
43
|
+
# Configure Ollama
|
44
|
+
config.configure_provider(:ollama, host: 'http://localhost:11434')
|
45
|
+
end
|
46
|
+
```
|
47
|
+
|
48
|
+
### Rails Integration
|
49
|
+
|
50
|
+
LastLLM automatically integrates with Rails applications. Create a `config/last_llm.yml` file:
|
51
|
+
|
52
|
+
```yaml
|
53
|
+
default_provider: openai
|
54
|
+
default_model: gpt-3.5-turbo
|
55
|
+
globals:
|
56
|
+
timeout: 30
|
57
|
+
max_retries: 3
|
58
|
+
```
|
59
|
+
|
60
|
+
## Usage
|
61
|
+
|
62
|
+
### Basic Text Generation
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
client = LastLLM.client
|
66
|
+
response = client.generate_text("What is the capital of France?")
|
67
|
+
```
|
68
|
+
|
69
|
+
### Structured Data Generation
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
schema = Dry::Schema.JSON do
|
73
|
+
required(:name).filled(:string)
|
74
|
+
required(:age).filled(:integer)
|
75
|
+
optional(:email).maybe(:string)
|
76
|
+
end
|
77
|
+
|
78
|
+
client = LastLLM.client
|
79
|
+
result = client.generate_object("Generate information about a person", schema)
|
80
|
+
```
|
81
|
+
|
82
|
+
### Tool Calling
|
83
|
+
|
84
|
+
```ruby
|
85
|
+
calculator = LastLLM::Tool.new(
|
86
|
+
name: "calculator",
|
87
|
+
description: "Perform mathematical calculations",
|
88
|
+
parameters: {
|
89
|
+
type: "object",
|
90
|
+
properties: {
|
91
|
+
operation: {
|
92
|
+
type: "string",
|
93
|
+
enum: ["add", "subtract", "multiply", "divide"]
|
94
|
+
},
|
95
|
+
a: { type: "number" },
|
96
|
+
b: { type: "number" }
|
97
|
+
},
|
98
|
+
required: ["operation", "a", "b"]
|
99
|
+
},
|
100
|
+
function: ->(params) {
|
101
|
+
case params[:operation]
|
102
|
+
when "add"
|
103
|
+
{ result: params[:a] + params[:b] }
|
104
|
+
end
|
105
|
+
}
|
106
|
+
)
|
107
|
+
```
|
108
|
+
|
109
|
+
## Error Handling
|
110
|
+
|
111
|
+
LastLLM provides several error classes:
|
112
|
+
- `LastLLM::Error`: Base error class
|
113
|
+
- `LastLLM::ConfigurationError`: Configuration-related errors
|
114
|
+
- `LastLLM::ValidationError`: Schema validation errors
|
115
|
+
- `LastLLM::ApiError`: API request errors
|
116
|
+
|
117
|
+
## Development
|
118
|
+
|
119
|
+
After checking out the repo, run `bundle install` to install dependencies. Then, run `rspec` to run the tests.
|
120
|
+
|
121
|
+
## Contributing
|
122
|
+
|
123
|
+
Bug reports and pull requests are welcome on GitHub.
|
124
|
+
# LastLLM
|
125
|
+
|
126
|
+
LastLLM is a unified client for interacting with various LLM (Large Language Model) providers. It provides a consistent interface for text generation, structured data generation, and tool calling across different LLM services.
|
127
|
+
|
128
|
+
## Features
|
129
|
+
|
130
|
+
- Unified interface for multiple LLM providers:
|
131
|
+
- OpenAI
|
132
|
+
- Anthropic
|
133
|
+
- Google Gemini
|
134
|
+
- Deepseek
|
135
|
+
- Ollama
|
136
|
+
- Text generation
|
137
|
+
- Structured data generation with schema validation
|
138
|
+
- Tool/function calling support
|
139
|
+
- Rails integration
|
140
|
+
- Configuration management
|
141
|
+
- Error handling
|
142
|
+
|
143
|
+
## Installation
|
144
|
+
|
145
|
+
Add this line to your application's Gemfile:
|
146
|
+
|
147
|
+
```ruby
|
148
|
+
gem 'last_llm'
|
149
|
+
```
|
150
|
+
|
151
|
+
## Configuration
|
152
|
+
|
153
|
+
Configure LastLLM globally or per instance:
|
154
|
+
|
155
|
+
```ruby
|
156
|
+
LastLLM.configure do |config|
|
157
|
+
config.default_provider = :openai
|
158
|
+
config.default_model = 'gpt-3.5-turbo'
|
159
|
+
|
160
|
+
# Configure OpenAI
|
161
|
+
config.configure_provider(:openai, api_key: 'your-api-key')
|
162
|
+
|
163
|
+
# Configure Anthropic
|
164
|
+
config.configure_provider(:anthropic, api_key: 'your-api-key')
|
165
|
+
|
166
|
+
# Configure Ollama
|
167
|
+
config.configure_provider(:ollama, host: 'http://localhost:11434')
|
168
|
+
end
|
169
|
+
```
|
170
|
+
|
171
|
+
### Rails Integration
|
172
|
+
|
173
|
+
LastLLM automatically integrates with Rails applications. Create a `config/last_llm.yml` file:
|
174
|
+
|
175
|
+
```yaml
|
176
|
+
default_provider: openai
|
177
|
+
default_model: gpt-3.5-turbo
|
178
|
+
globals:
|
179
|
+
timeout: 30
|
180
|
+
max_retries: 3
|
181
|
+
```
|
182
|
+
|
183
|
+
## Usage
|
184
|
+
|
185
|
+
### Basic Text Generation
|
186
|
+
|
187
|
+
```ruby
|
188
|
+
client = LastLLM.client
|
189
|
+
response = client.generate_text("What is the capital of France?")
|
190
|
+
```
|
191
|
+
|
192
|
+
### Structured Data Generation
|
193
|
+
|
194
|
+
```ruby
|
195
|
+
schema = Dry::Schema.JSON do
|
196
|
+
required(:name).filled(:string)
|
197
|
+
required(:age).filled(:integer)
|
198
|
+
optional(:email).maybe(:string)
|
199
|
+
end
|
200
|
+
|
201
|
+
client = LastLLM.client
|
202
|
+
result = client.generate_object("Generate information about a person", schema)
|
203
|
+
```
|
204
|
+
|
205
|
+
### Tool Calling
|
206
|
+
|
207
|
+
```ruby
|
208
|
+
calculator = LastLLM::Tool.new(
|
209
|
+
name: "calculator",
|
210
|
+
description: "Perform mathematical calculations",
|
211
|
+
parameters: {
|
212
|
+
type: "object",
|
213
|
+
properties: {
|
214
|
+
operation: {
|
215
|
+
type: "string",
|
216
|
+
enum: ["add", "subtract", "multiply", "divide"]
|
217
|
+
},
|
218
|
+
a: { type: "number" },
|
219
|
+
b: { type: "number" }
|
220
|
+
},
|
221
|
+
required: ["operation", "a", "b"]
|
222
|
+
},
|
223
|
+
function: ->(params) {
|
224
|
+
case params[:operation]
|
225
|
+
when "add"
|
226
|
+
{ result: params[:a] + params[:b] }
|
227
|
+
end
|
228
|
+
}
|
229
|
+
)
|
230
|
+
```
|
231
|
+
|
232
|
+
## Error Handling
|
233
|
+
|
234
|
+
LastLLM provides several error classes:
|
235
|
+
- `LastLLM::Error`: Base error class
|
236
|
+
- `LastLLM::ConfigurationError`: Configuration-related errors
|
237
|
+
- `LastLLM::ValidationError`: Schema validation errors
|
238
|
+
- `LastLLM::ApiError`: API request errors
|
239
|
+
|
240
|
+
## Development
|
241
|
+
|
242
|
+
After checking out the repo, run `bundle install` to install dependencies. Then, run `rspec` to run the tests.
|
243
|
+
|
244
|
+
## Contributing
|
245
|
+
|
246
|
+
Bug reports and pull requests are welcome on GitHub.
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'last_llm/completion'
|
4
|
+
require 'last_llm/structured_output'
|
5
|
+
require 'last_llm/schema'
|
6
|
+
require 'last_llm/providers/constants'
|
7
|
+
|
8
|
+
module LastLLM
|
9
|
+
# Client for interacting with LLM providers
|
10
|
+
# This is the main interface for the LastLLM library
|
11
|
+
class Client
|
12
|
+
# Client configuration
|
13
|
+
attr_reader :configuration
|
14
|
+
|
15
|
+
# Current provider instance
|
16
|
+
attr_reader :provider
|
17
|
+
|
18
|
+
# Initialize a new client
|
19
|
+
# @param config [Configuration, nil] The configuration to use
|
20
|
+
# @param options [Hash] Additional options
|
21
|
+
# @option options [Symbol] :provider The provider to use
|
22
|
+
def initialize(config = nil, options = {})
|
23
|
+
@configuration = case config
|
24
|
+
when Configuration
|
25
|
+
config
|
26
|
+
when Hash
|
27
|
+
Configuration.new(config)
|
28
|
+
else
|
29
|
+
# When no config provided, default to test mode in test environment
|
30
|
+
# Force test_mode to true when running in RSpec
|
31
|
+
test_mode = true
|
32
|
+
Configuration.new(test_mode: test_mode)
|
33
|
+
end
|
34
|
+
|
35
|
+
provider_name = options[:provider] || @configuration.default_provider
|
36
|
+
@provider = create_provider(provider_name)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Text generation methods
|
40
|
+
|
41
|
+
# Generate text in a single call
|
42
|
+
# @param prompt [String] The input text
|
43
|
+
# @param options [Hash] Options to control generation
|
44
|
+
# @return [String] The generated text
|
45
|
+
def generate_text(prompt, options = {})
|
46
|
+
@provider.generate_text(prompt, options)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Generate a structured object from a prompt
|
50
|
+
# @param prompt [String] The prompt to generate the object from
|
51
|
+
# @param schema [Dry::Schema::JSON] The schema to validate against
|
52
|
+
# @param options [Hash] Generation options
|
53
|
+
# @option options [String] :model The model to use
|
54
|
+
# @option options [Float] :temperature (0.2) The temperature to use
|
55
|
+
# @return [Hash] The generated object
|
56
|
+
# @raise [ValidationError] If the generated object fails validation
|
57
|
+
def generate_object(prompt, schema, options = {})
|
58
|
+
structured_output = LastLLM::StructuredOutput.new(self)
|
59
|
+
structured_output.generate(prompt, schema, options)
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
# Create a provider instance
|
65
|
+
# @param provider_name [Symbol] The provider name
|
66
|
+
# @return [Provider] The provider instance
|
67
|
+
# @raise [ConfigurationError] If the provider is not configured
|
68
|
+
def create_provider(provider_name)
|
69
|
+
# Validate provider configuration
|
70
|
+
@configuration.validate_provider_config!(provider_name)
|
71
|
+
|
72
|
+
# Get provider configuration with test_mode applied if needed
|
73
|
+
provider_config = @configuration.provider_config(provider_name)
|
74
|
+
|
75
|
+
# Create provider instance
|
76
|
+
case provider_name
|
77
|
+
when Providers::Constants::OPENAI
|
78
|
+
require 'last_llm/providers/openai'
|
79
|
+
Providers::OpenAI.new(provider_config)
|
80
|
+
when Providers::Constants::ANTHROPIC
|
81
|
+
require 'last_llm/providers/anthropic'
|
82
|
+
Providers::Anthropic.new(provider_config)
|
83
|
+
when Providers::Constants::GOOGLE_GEMINI
|
84
|
+
require 'last_llm/providers/google_gemini'
|
85
|
+
Providers::GoogleGemini.new(provider_config)
|
86
|
+
when Providers::Constants::DEEPSEEK
|
87
|
+
require 'last_llm/providers/deepseek'
|
88
|
+
Providers::Deepseek.new(provider_config)
|
89
|
+
when Providers::Constants::OLLAMA
|
90
|
+
require 'last_llm/providers/ollama'
|
91
|
+
Providers::Ollama.new(provider_config)
|
92
|
+
when Providers::Constants::TEST
|
93
|
+
require 'last_llm/providers/test_provider'
|
94
|
+
Providers::TestProvider.new(provider_config)
|
95
|
+
else
|
96
|
+
raise ConfigurationError, "Unknown provider: #{provider_name}"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LastLLM
|
4
|
+
# Represents a completion response from an LLM provider
|
5
|
+
# Contains the generated text and any additional metadata
|
6
|
+
class Completion
|
7
|
+
def initialize(client)
|
8
|
+
@client = client
|
9
|
+
end
|
10
|
+
|
11
|
+
# Generate text completion in a single response
|
12
|
+
# @param prompt [String] The input text to complete
|
13
|
+
# @param options [Hash] Options to control the completion
|
14
|
+
# @return [String] The generated text
|
15
|
+
def generate(prompt, options = {})
|
16
|
+
@client.provider.generate_text(prompt, options)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'last_llm/providers/constants'
|
4
|
+
|
5
|
+
module LastLLM
|
6
|
+
# Configuration class for LastLLM
|
7
|
+
# Handles global and provider-specific settings
|
8
|
+
class Configuration
|
9
|
+
# Provider validation configuration
|
10
|
+
PROVIDER_VALIDATIONS = {
|
11
|
+
Providers::Constants::OPENAI => { required: [:api_key] },
|
12
|
+
Providers::Constants::ANTHROPIC => { required: [:api_key] },
|
13
|
+
Providers::Constants::GOOGLE_GEMINI => { required: [:api_key] },
|
14
|
+
Providers::Constants::DEEPSEEK => { required: [:api_key] },
|
15
|
+
Providers::Constants::OLLAMA => {
|
16
|
+
required: [],
|
17
|
+
custom: lambda { |config|
|
18
|
+
return if config[:api_key]
|
19
|
+
raise ConfigurationError, 'Ollama host is required when no API key is provided' unless config[:host]
|
20
|
+
}
|
21
|
+
}
|
22
|
+
}.freeze
|
23
|
+
# Default provider to use
|
24
|
+
attr_accessor :default_provider
|
25
|
+
|
26
|
+
# Default model to use
|
27
|
+
attr_accessor :default_model
|
28
|
+
|
29
|
+
# Provider-specific configurations
|
30
|
+
attr_reader :providers
|
31
|
+
|
32
|
+
attr_reader :base_url
|
33
|
+
|
34
|
+
# Global settings
|
35
|
+
attr_reader :globals
|
36
|
+
|
37
|
+
# Initialize a new configuration
|
38
|
+
# @param options [Hash] Configuration options
|
39
|
+
# @option options [Symbol] :default_provider (:openai) The default provider to use
|
40
|
+
# @option options [String] :default_model ('gpt-3.5-turbo') The default model to use
|
41
|
+
# @option options [Boolean] :test_mode (false) Whether to run in test mode
|
42
|
+
def initialize(options = {})
|
43
|
+
@default_provider = options[:default_provider] || Providers::Constants::OPENAI
|
44
|
+
@default_model = options[:default_model] || 'gpt-3.5-turbo'
|
45
|
+
@test_mode = options[:test_mode] || false
|
46
|
+
@providers = {}
|
47
|
+
@globals = {
|
48
|
+
timeout: 60,
|
49
|
+
max_retries: 3,
|
50
|
+
retry_delay: 1
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
# Configure a provider with specific settings
|
55
|
+
# @param provider [Symbol] The provider name
|
56
|
+
# @param config [Hash] Provider-specific configuration
|
57
|
+
# @return [Hash] The updated provider configuration
|
58
|
+
def configure_provider(provider, config = {})
|
59
|
+
@providers[provider] ||= {}
|
60
|
+
@providers[provider].merge!(config)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Get provider configuration
|
64
|
+
# @param provider [Symbol] The provider name
|
65
|
+
# @return [Hash] The provider configuration
|
66
|
+
def provider_config(provider)
|
67
|
+
config = @providers[provider] || {}
|
68
|
+
# Ensure skip_validation is set when in test mode
|
69
|
+
config = config.dup
|
70
|
+
config[:skip_validation] = true if @test_mode
|
71
|
+
config
|
72
|
+
end
|
73
|
+
|
74
|
+
# Check if running in test mode
|
75
|
+
# @return [Boolean] Whether in test mode
|
76
|
+
def test_mode?
|
77
|
+
@test_mode
|
78
|
+
end
|
79
|
+
|
80
|
+
# Validate provider configuration based on requirements
|
81
|
+
# @param provider [Symbol] The provider to validate
|
82
|
+
# @raise [ConfigurationError] If the configuration is invalid
|
83
|
+
def validate_provider_config!(provider)
|
84
|
+
return if @test_mode
|
85
|
+
|
86
|
+
validation = PROVIDER_VALIDATIONS[provider]
|
87
|
+
raise ConfigurationError, "Unknown provider: #{provider}" unless validation
|
88
|
+
|
89
|
+
config = provider_config(provider)
|
90
|
+
|
91
|
+
validation[:required]&.each do |key|
|
92
|
+
raise ConfigurationError, "#{key.to_s.gsub('_', ' ')} is required for #{provider} provider" unless config[key]
|
93
|
+
end
|
94
|
+
|
95
|
+
return unless validation[:custom]
|
96
|
+
|
97
|
+
validation[:custom].call(config)
|
98
|
+
end
|
99
|
+
|
100
|
+
# Set a global configuration value
|
101
|
+
# @param key [Symbol] The configuration key
|
102
|
+
# @param value The configuration value
|
103
|
+
# @return The set value
|
104
|
+
def set_global(key, value)
|
105
|
+
@globals[key] = value
|
106
|
+
end
|
107
|
+
|
108
|
+
# Get a global configuration value
|
109
|
+
# @param key [Symbol] The configuration key
|
110
|
+
# @return The configuration value
|
111
|
+
def get_global(key)
|
112
|
+
@globals[key]
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Monkey patch Dry::Schema::JSON to add json_schema method
|
4
|
+
module Dry
|
5
|
+
module Schema
|
6
|
+
# Extensions to Dry::Schema::JSON for JSON Schema conversion
|
7
|
+
class JSON
|
8
|
+
# Convert the schema to a JSON schema hash
|
9
|
+
# @return [Hash] The JSON schema hash
|
10
|
+
def json_schema
|
11
|
+
# Extract schema information
|
12
|
+
json_schema = {
|
13
|
+
type: 'object',
|
14
|
+
properties: {},
|
15
|
+
required: []
|
16
|
+
}
|
17
|
+
|
18
|
+
# Process each rule in the schema
|
19
|
+
rules.each_value do |rule|
|
20
|
+
# Skip if rule is not a proper rule object
|
21
|
+
next unless rule.respond_to?(:name)
|
22
|
+
|
23
|
+
property_name = rule.name.to_s
|
24
|
+
property_def = {}
|
25
|
+
|
26
|
+
# Determine if the property is required
|
27
|
+
json_schema[:required] << property_name if rule.is_a?(Dry::Schema::Rule::Required)
|
28
|
+
|
29
|
+
# Determine the property type
|
30
|
+
if rule.respond_to?(:type) && rule.type.is_a?(Dry::Types::Nominal)
|
31
|
+
case rule.type.primitive
|
32
|
+
when String
|
33
|
+
property_def['type'] = 'string'
|
34
|
+
when Integer
|
35
|
+
property_def['type'] = 'integer'
|
36
|
+
when Float
|
37
|
+
property_def['type'] = 'number'
|
38
|
+
when TrueClass, FalseClass
|
39
|
+
property_def['type'] = 'boolean'
|
40
|
+
when Array
|
41
|
+
property_def['type'] = 'array'
|
42
|
+
# Try to determine the item type
|
43
|
+
property_def['items'] = if rule.type.respond_to?(:member) && rule.type.member.respond_to?(:primitive)
|
44
|
+
case rule.type.member.primitive
|
45
|
+
when String
|
46
|
+
{ 'type' => 'string' }
|
47
|
+
when Integer
|
48
|
+
{ 'type' => 'integer' }
|
49
|
+
when Float
|
50
|
+
{ 'type' => 'number' }
|
51
|
+
when TrueClass, FalseClass
|
52
|
+
{ 'type' => 'boolean' }
|
53
|
+
when Hash
|
54
|
+
{ 'type' => 'object' }
|
55
|
+
else
|
56
|
+
{}
|
57
|
+
end
|
58
|
+
else
|
59
|
+
{}
|
60
|
+
end
|
61
|
+
when Hash
|
62
|
+
property_def['type'] = 'object'
|
63
|
+
# For nested objects, we'd need a more sophisticated approach
|
64
|
+
else
|
65
|
+
property_def['type'] = 'string' # Default to string
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
json_schema[:properties][property_name] = property_def
|
70
|
+
end
|
71
|
+
|
72
|
+
json_schema
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|