ruby_llm 0.1.0.pre49 → 1.0.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/.github/workflows/cicd.yml +49 -0
- data/.gitignore +2 -1
- data/.overcommit.yml +1 -1
- data/CONTRIBUTING.md +207 -0
- data/Gemfile +1 -0
- data/README.md +50 -18
- data/lib/ruby_llm/chat.rb +1 -1
- data/lib/ruby_llm/models.json +389 -43
- data/lib/ruby_llm/models.rb +22 -16
- data/lib/ruby_llm/provider.rb +12 -2
- data/lib/ruby_llm/providers/gemini/models.rb +0 -8
- data/lib/ruby_llm/providers/openai/capabilities.rb +41 -4
- data/lib/ruby_llm/tool.rb +15 -7
- data/lib/ruby_llm/version.rb +1 -1
- data/lib/ruby_llm.rb +2 -0
- data/lib/tasks/models.rake +6 -10
- data/lib/tasks/vcr.rake +114 -0
- data/ruby_llm.gemspec +1 -0
- metadata +18 -3
- data/.rspec_status +0 -50
data/lib/ruby_llm/models.rb
CHANGED
@@ -12,22 +12,26 @@ module RubyLLM
|
|
12
12
|
class Models
|
13
13
|
include Enumerable
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
# Delegate class methods to the singleton instance
|
16
|
+
class << self
|
17
|
+
def instance
|
18
|
+
@instance ||= new
|
19
|
+
end
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
-
|
21
|
+
def provider_for(model)
|
22
|
+
Provider.for(model)
|
23
|
+
end
|
22
24
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
25
|
+
def models_file
|
26
|
+
File.expand_path('models.json', __dir__)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Class method to refresh model data
|
30
|
+
def refresh!
|
31
|
+
models = RubyLLM.providers.flat_map(&:list_models).sort_by(&:id)
|
32
|
+
@instance = new(models)
|
33
|
+
end
|
28
34
|
|
29
|
-
# Delegate class methods to the singleton instance
|
30
|
-
class << self
|
31
35
|
def method_missing(method, ...)
|
32
36
|
if instance.respond_to?(method)
|
33
37
|
instance.send(method, ...)
|
@@ -48,12 +52,16 @@ module RubyLLM
|
|
48
52
|
|
49
53
|
# Load models from the JSON file
|
50
54
|
def load_models
|
51
|
-
data = JSON.parse(File.read(
|
55
|
+
data = JSON.parse(File.read(self.class.models_file))
|
52
56
|
data.map { |model| ModelInfo.new(model.transform_keys(&:to_sym)) }
|
53
57
|
rescue Errno::ENOENT
|
54
58
|
[] # Return empty array if file doesn't exist yet
|
55
59
|
end
|
56
60
|
|
61
|
+
def save_models
|
62
|
+
File.write(self.class.models_file, JSON.pretty_generate(all.map(&:to_h)))
|
63
|
+
end
|
64
|
+
|
57
65
|
# Return all models in the collection
|
58
66
|
def all
|
59
67
|
@models
|
@@ -103,8 +111,6 @@ module RubyLLM
|
|
103
111
|
# Instance method to refresh models
|
104
112
|
def refresh!
|
105
113
|
self.class.refresh!
|
106
|
-
# Return self for method chaining
|
107
|
-
self
|
108
114
|
end
|
109
115
|
end
|
110
116
|
end
|
data/lib/ruby_llm/provider.rb
CHANGED
@@ -8,8 +8,18 @@ module RubyLLM
|
|
8
8
|
# Common functionality for all LLM providers. Implements the core provider
|
9
9
|
# interface so specific providers only need to implement a few key methods.
|
10
10
|
module Methods # rubocop:disable Metrics/ModuleLength
|
11
|
-
def complete(messages, tools:, temperature:, model:, &block)
|
12
|
-
|
11
|
+
def complete(messages, tools:, temperature:, model:, &block) # rubocop:disable Metrics/MethodLength
|
12
|
+
normalized_temperature = if capabilities.respond_to?(:normalize_temperature)
|
13
|
+
capabilities.normalize_temperature(temperature, model)
|
14
|
+
else
|
15
|
+
temperature
|
16
|
+
end
|
17
|
+
|
18
|
+
payload = render_payload(messages,
|
19
|
+
tools: tools,
|
20
|
+
temperature: normalized_temperature,
|
21
|
+
model: model,
|
22
|
+
stream: block_given?)
|
13
23
|
|
14
24
|
if block_given?
|
15
25
|
stream_response payload, &block
|
@@ -10,14 +10,6 @@ module RubyLLM
|
|
10
10
|
'models'
|
11
11
|
end
|
12
12
|
|
13
|
-
def list_models
|
14
|
-
response = connection.get("models?key=#{RubyLLM.config.gemini_api_key}") do |req|
|
15
|
-
req.headers.merge! headers
|
16
|
-
end
|
17
|
-
|
18
|
-
parse_list_models_response(response, slug, capabilities)
|
19
|
-
end
|
20
|
-
|
21
13
|
private
|
22
14
|
|
23
15
|
def parse_list_models_response(response, slug, capabilities) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
|
@@ -50,15 +50,42 @@ module RubyLLM
|
|
50
50
|
# Determines if the model supports vision capabilities
|
51
51
|
# @param model_id [String] the model identifier
|
52
52
|
# @return [Boolean] true if the model supports vision
|
53
|
-
def supports_vision?(model_id)
|
54
|
-
|
53
|
+
def supports_vision?(model_id) # rubocop:disable Metrics/MethodLength
|
54
|
+
supporting_patterns = [
|
55
|
+
/^o1$/,
|
56
|
+
/^o1-(?!.*mini|.*preview).*$/,
|
57
|
+
/gpt-4\.5/,
|
58
|
+
/^gpt-4o$/,
|
59
|
+
/gpt-4o-2024/,
|
60
|
+
/gpt-4o-search/,
|
61
|
+
/^gpt-4o-mini$/,
|
62
|
+
/gpt-4o-mini-2024/,
|
63
|
+
/gpt-4o-mini-search/,
|
64
|
+
/chatgpt-4o/,
|
65
|
+
/gpt-4-turbo-2024/,
|
66
|
+
/computer-use-preview/,
|
67
|
+
/omni-moderation/
|
68
|
+
]
|
69
|
+
supporting_patterns.any? { |regex| model_id.match?(regex) }
|
55
70
|
end
|
56
71
|
|
57
72
|
# Determines if the model supports function calling
|
58
73
|
# @param model_id [String] the model identifier
|
59
74
|
# @return [Boolean] true if the model supports functions
|
60
|
-
def supports_functions?(model_id)
|
61
|
-
|
75
|
+
def supports_functions?(model_id) # rubocop:disable Metrics/MethodLength
|
76
|
+
supporting_patterns = [
|
77
|
+
/^o1$/,
|
78
|
+
/gpt-4o/,
|
79
|
+
/gpt-4\.5/,
|
80
|
+
/chatgpt-4o/,
|
81
|
+
/gpt-4-turbo/,
|
82
|
+
/computer-use-preview/,
|
83
|
+
/o1-preview/,
|
84
|
+
/o1-\d{4}-\d{2}-\d{2}/,
|
85
|
+
/o1-pro/,
|
86
|
+
/o3-mini/
|
87
|
+
]
|
88
|
+
supporting_patterns.any? { |regex| model_id.match?(regex) }
|
62
89
|
end
|
63
90
|
|
64
91
|
# Determines if the model supports audio input/output
|
@@ -230,6 +257,16 @@ module RubyLLM
|
|
230
257
|
.gsub('Omni Moderation', 'Omni-Moderation')
|
231
258
|
.gsub('Text Moderation', 'Text-Moderation')
|
232
259
|
end
|
260
|
+
|
261
|
+
def normalize_temperature(temperature, model_id)
|
262
|
+
if model_id.match?(/o[13]/)
|
263
|
+
# O1/O3 models always use temperature 1.0
|
264
|
+
RubyLLM.logger.debug "Model #{model_id} requires temperature=1.0, ignoring provided value"
|
265
|
+
1.0
|
266
|
+
else
|
267
|
+
temperature
|
268
|
+
end
|
269
|
+
end
|
233
270
|
end
|
234
271
|
end
|
235
272
|
end
|
data/lib/ruby_llm/tool.rb
CHANGED
@@ -18,14 +18,19 @@ module RubyLLM
|
|
18
18
|
# interface for defining parameters and implementing tool behavior.
|
19
19
|
#
|
20
20
|
# Example:
|
21
|
-
#
|
22
|
-
# description "Performs arithmetic calculations"
|
23
|
-
# param :expression, type: :string, desc: "Math expression to evaluate"
|
21
|
+
# require 'tzinfo'
|
24
22
|
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
23
|
+
# class TimeInfo < RubyLLM::Tool
|
24
|
+
# description 'Gets the current time in various timezones'
|
25
|
+
# param :timezone, desc: "Timezone name (e.g., 'UTC', 'America/New_York')"
|
26
|
+
#
|
27
|
+
# def execute(timezone:)
|
28
|
+
# time = TZInfo::Timezone.get(timezone).now.strftime('%Y-%m-%d %H:%M:%S')
|
29
|
+
# "Current time in #{timezone}: #{time}"
|
30
|
+
# rescue StandardError => e
|
31
|
+
# { error: e.message }
|
32
|
+
# end
|
33
|
+
# end
|
29
34
|
class Tool
|
30
35
|
class << self
|
31
36
|
def description(text = nil)
|
@@ -45,6 +50,9 @@ module RubyLLM
|
|
45
50
|
|
46
51
|
def name
|
47
52
|
self.class.name
|
53
|
+
.unicode_normalize(:nfkd)
|
54
|
+
.encode('ASCII', replace: '')
|
55
|
+
.gsub(/[^a-zA-Z0-9_-]/, '-')
|
48
56
|
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
49
57
|
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
50
58
|
.downcase
|
data/lib/ruby_llm/version.rb
CHANGED
data/lib/ruby_llm.rb
CHANGED
@@ -17,6 +17,8 @@ loader.inflector.inflect(
|
|
17
17
|
'api' => 'API',
|
18
18
|
'deepseek' => 'DeepSeek'
|
19
19
|
)
|
20
|
+
loader.ignore("#{__dir__}/ruby_llm/railtie")
|
21
|
+
loader.ignore("#{__dir__}/ruby_llm/active_record")
|
20
22
|
loader.setup
|
21
23
|
|
22
24
|
# A delightful Ruby interface to modern AI language models.
|
data/lib/tasks/models.rake
CHANGED
@@ -2,7 +2,9 @@
|
|
2
2
|
|
3
3
|
require 'English'
|
4
4
|
require 'faraday'
|
5
|
+
require 'fileutils'
|
5
6
|
require 'nokogiri'
|
7
|
+
require 'ruby_llm'
|
6
8
|
|
7
9
|
# URLs to process
|
8
10
|
PROVIDER_DOCS = {
|
@@ -64,8 +66,6 @@ end
|
|
64
66
|
namespace :models do # rubocop:disable Metrics/BlockLength
|
65
67
|
desc 'Update available models from providers'
|
66
68
|
task :update do
|
67
|
-
require 'ruby_llm'
|
68
|
-
|
69
69
|
# Configure API keys
|
70
70
|
RubyLLM.configure do |config|
|
71
71
|
config.openai_api_key = ENV.fetch('OPENAI_API_KEY')
|
@@ -74,15 +74,13 @@ namespace :models do # rubocop:disable Metrics/BlockLength
|
|
74
74
|
config.deepseek_api_key = ENV.fetch('DEEPSEEK_API_KEY')
|
75
75
|
end
|
76
76
|
|
77
|
-
|
78
|
-
models
|
79
|
-
# Write to models.json
|
80
|
-
File.write(File.expand_path('../ruby_llm/models.json', __dir__), JSON.pretty_generate(models.map(&:to_h)))
|
77
|
+
models = RubyLLM.models.refresh!
|
78
|
+
models.save_models
|
81
79
|
|
82
|
-
puts "Updated models.json with #{models.size} models:"
|
80
|
+
puts "Updated models.json with #{models.all.size} models:"
|
83
81
|
RubyLLM::Provider.providers.each do |provider_sym, provider_module|
|
84
82
|
provider_name = provider_module.to_s.split('::').last
|
85
|
-
provider_models = models.select { |m| m.provider == provider_sym.to_s }
|
83
|
+
provider_models = models.all.select { |m| m.provider == provider_sym.to_s }
|
86
84
|
puts "#{provider_name} models: #{provider_models.size}"
|
87
85
|
end
|
88
86
|
end
|
@@ -91,8 +89,6 @@ namespace :models do # rubocop:disable Metrics/BlockLength
|
|
91
89
|
task :update_capabilities do # rubocop:disable Metrics/BlockLength
|
92
90
|
# Check if a specific provider was requested
|
93
91
|
target_provider = ENV['PROVIDER']&.to_sym
|
94
|
-
require 'ruby_llm'
|
95
|
-
require 'fileutils'
|
96
92
|
|
97
93
|
# Configure API keys
|
98
94
|
RubyLLM.configure do |config|
|
data/lib/tasks/vcr.rake
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Helper functions at the top level
|
4
|
+
def record_all_cassettes(cassette_dir)
|
5
|
+
# Re-record all cassettes
|
6
|
+
FileUtils.rm_rf(cassette_dir)
|
7
|
+
FileUtils.mkdir_p(cassette_dir)
|
8
|
+
|
9
|
+
puts 'Recording cassettes for all providers...'
|
10
|
+
run_tests
|
11
|
+
puts 'Done recording. Please review the new cassettes.'
|
12
|
+
end
|
13
|
+
|
14
|
+
def record_for_providers(providers, cassette_dir) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
|
15
|
+
# Get the list of available providers from RubyLLM itself
|
16
|
+
all_providers = RubyLLM::Provider.providers.keys.map(&:to_s)
|
17
|
+
|
18
|
+
# Check for valid providers
|
19
|
+
if providers.empty?
|
20
|
+
puts "Please specify providers or 'all'. Example: rake vcr:record[openai,anthropic]"
|
21
|
+
puts "Available providers: #{all_providers.join(', ')}"
|
22
|
+
return
|
23
|
+
end
|
24
|
+
|
25
|
+
invalid_providers = providers - all_providers
|
26
|
+
if invalid_providers.any?
|
27
|
+
puts "Invalid providers: #{invalid_providers.join(', ')}"
|
28
|
+
puts "Available providers: #{all_providers.join(', ')}"
|
29
|
+
return
|
30
|
+
end
|
31
|
+
|
32
|
+
# Get URL patterns from the providers themselves
|
33
|
+
provider_patterns = get_provider_patterns(providers)
|
34
|
+
|
35
|
+
puts "Finding cassettes for providers: #{providers.join(', ')}"
|
36
|
+
|
37
|
+
# Find and delete matching cassettes
|
38
|
+
cassettes_to_delete = find_matching_cassettes(cassette_dir, provider_patterns)
|
39
|
+
|
40
|
+
if cassettes_to_delete.empty?
|
41
|
+
puts 'No cassettes found for the specified providers.'
|
42
|
+
puts 'Running tests to record new cassettes...'
|
43
|
+
else
|
44
|
+
delete_cassettes(cassettes_to_delete)
|
45
|
+
puts "\nRunning tests to record new cassettes..."
|
46
|
+
end
|
47
|
+
|
48
|
+
run_tests
|
49
|
+
|
50
|
+
puts "\nDone recording cassettes for #{providers.join(', ')}."
|
51
|
+
puts 'Please review the updated cassettes for sensitive information.'
|
52
|
+
end
|
53
|
+
|
54
|
+
def get_provider_patterns(providers) # rubocop:disable Metrics/MethodLength
|
55
|
+
provider_patterns = {}
|
56
|
+
|
57
|
+
providers.each do |provider_name|
|
58
|
+
provider_module = RubyLLM::Provider.providers[provider_name.to_sym]
|
59
|
+
next unless provider_module
|
60
|
+
|
61
|
+
# Extract the base URL from the provider's api_base method
|
62
|
+
api_base = provider_module.api_base.to_s
|
63
|
+
|
64
|
+
# Create a regex pattern from the domain
|
65
|
+
next unless api_base && !api_base.empty?
|
66
|
+
|
67
|
+
domain = URI.parse(api_base).host
|
68
|
+
pattern = Regexp.new(Regexp.escape(domain))
|
69
|
+
provider_patterns[provider_name] = pattern
|
70
|
+
end
|
71
|
+
|
72
|
+
provider_patterns
|
73
|
+
end
|
74
|
+
|
75
|
+
def find_matching_cassettes(dir, patterns)
|
76
|
+
cassettes = []
|
77
|
+
|
78
|
+
Dir.glob("#{dir}/**/*.yml").each do |file|
|
79
|
+
content = File.read(file)
|
80
|
+
cassettes << file if patterns.values.any? { |pattern| content.match?(pattern) }
|
81
|
+
end
|
82
|
+
|
83
|
+
cassettes
|
84
|
+
end
|
85
|
+
|
86
|
+
def delete_cassettes(cassettes)
|
87
|
+
puts "Deleting #{cassettes.size} cassettes for re-recording:"
|
88
|
+
cassettes.each do |file|
|
89
|
+
puts " - #{File.basename(file)}"
|
90
|
+
File.delete(file)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def run_tests
|
95
|
+
system('bundle exec rspec') || abort('Tests failed')
|
96
|
+
end
|
97
|
+
|
98
|
+
namespace :vcr do
|
99
|
+
desc 'Record VCR cassettes (rake vcr:record[all] or vcr:record[openai,anthropic])'
|
100
|
+
task :record, [:providers] do |_, args|
|
101
|
+
require 'fileutils'
|
102
|
+
require 'ruby_llm'
|
103
|
+
|
104
|
+
providers = (args[:providers] || '').downcase.split(',')
|
105
|
+
cassette_dir = 'spec/fixtures/vcr_cassettes'
|
106
|
+
FileUtils.mkdir_p(cassette_dir)
|
107
|
+
|
108
|
+
if providers.include?('all')
|
109
|
+
record_all_cassettes(cassette_dir)
|
110
|
+
else
|
111
|
+
record_for_providers(providers, cassette_dir)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
data/ruby_llm.gemspec
CHANGED
@@ -35,6 +35,7 @@ Gem::Specification.new do |spec|
|
|
35
35
|
spec.require_paths = ['lib']
|
36
36
|
|
37
37
|
# Runtime dependencies
|
38
|
+
spec.add_dependency 'base64'
|
38
39
|
spec.add_dependency 'event_stream_parser', '~> 1'
|
39
40
|
spec.add_dependency 'faraday', '~> 2'
|
40
41
|
spec.add_dependency 'faraday-multipart', '~> 1'
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby_llm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Carmine Paolino
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-03-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: base64
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: event_stream_parser
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -96,9 +110,9 @@ files:
|
|
96
110
|
- ".gitignore"
|
97
111
|
- ".overcommit.yml"
|
98
112
|
- ".rspec"
|
99
|
-
- ".rspec_status"
|
100
113
|
- ".rubocop.yml"
|
101
114
|
- ".yardopts"
|
115
|
+
- CONTRIBUTING.md
|
102
116
|
- Gemfile
|
103
117
|
- LICENSE
|
104
118
|
- README.md
|
@@ -153,6 +167,7 @@ files:
|
|
153
167
|
- lib/ruby_llm/tool_call.rb
|
154
168
|
- lib/ruby_llm/version.rb
|
155
169
|
- lib/tasks/models.rake
|
170
|
+
- lib/tasks/vcr.rake
|
156
171
|
- ruby_llm.gemspec
|
157
172
|
homepage: https://rubyllm.com
|
158
173
|
licenses:
|
data/.rspec_status
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
example_id | status | run_time |
|
2
|
-
-------------------------------------------------- | ------ | --------------- |
|
3
|
-
./spec/ruby_llm/active_record/acts_as_spec.rb[1:1] | passed | 3.38 seconds |
|
4
|
-
./spec/ruby_llm/active_record/acts_as_spec.rb[1:2] | passed | 2.48 seconds |
|
5
|
-
./spec/ruby_llm/chat_content_spec.rb[1:1:1] | passed | 2.74 seconds |
|
6
|
-
./spec/ruby_llm/chat_content_spec.rb[1:1:2] | passed | 1.29 seconds |
|
7
|
-
./spec/ruby_llm/chat_content_spec.rb[1:1:3] | passed | 2.54 seconds |
|
8
|
-
./spec/ruby_llm/chat_content_spec.rb[1:2:1] | passed | 2.77 seconds |
|
9
|
-
./spec/ruby_llm/chat_content_spec.rb[1:2:2] | passed | 2.1 seconds |
|
10
|
-
./spec/ruby_llm/chat_pdf_spec.rb[1:1:1] | passed | 7.75 seconds |
|
11
|
-
./spec/ruby_llm/chat_pdf_spec.rb[1:1:2] | passed | 13.88 seconds |
|
12
|
-
./spec/ruby_llm/chat_spec.rb[1:1:1:1] | passed | 1.02 seconds |
|
13
|
-
./spec/ruby_llm/chat_spec.rb[1:1:1:2] | passed | 3.95 seconds |
|
14
|
-
./spec/ruby_llm/chat_spec.rb[1:1:2:1] | passed | 0.4854 seconds |
|
15
|
-
./spec/ruby_llm/chat_spec.rb[1:1:2:2] | passed | 1.37 seconds |
|
16
|
-
./spec/ruby_llm/chat_spec.rb[1:1:3:1] | passed | 7.34 seconds |
|
17
|
-
./spec/ruby_llm/chat_spec.rb[1:1:3:2] | passed | 19.22 seconds |
|
18
|
-
./spec/ruby_llm/chat_spec.rb[1:1:4:1] | passed | 3.15 seconds |
|
19
|
-
./spec/ruby_llm/chat_spec.rb[1:1:4:2] | passed | 2.51 seconds |
|
20
|
-
./spec/ruby_llm/chat_streaming_spec.rb[1:1:1:1] | passed | 0.91374 seconds |
|
21
|
-
./spec/ruby_llm/chat_streaming_spec.rb[1:1:2:1] | passed | 0.50088 seconds |
|
22
|
-
./spec/ruby_llm/chat_streaming_spec.rb[1:1:3:1] | passed | 5.69 seconds |
|
23
|
-
./spec/ruby_llm/chat_streaming_spec.rb[1:1:4:1] | passed | 1.22 seconds |
|
24
|
-
./spec/ruby_llm/chat_tools_spec.rb[1:1:1] | passed | 4.26 seconds |
|
25
|
-
./spec/ruby_llm/chat_tools_spec.rb[1:1:2] | passed | 6.16 seconds |
|
26
|
-
./spec/ruby_llm/chat_tools_spec.rb[1:1:3] | passed | 11.15 seconds |
|
27
|
-
./spec/ruby_llm/chat_tools_spec.rb[1:1:4] | passed | 1.3 seconds |
|
28
|
-
./spec/ruby_llm/chat_tools_spec.rb[1:1:5] | passed | 2.71 seconds |
|
29
|
-
./spec/ruby_llm/chat_tools_spec.rb[1:1:6] | passed | 2.43 seconds |
|
30
|
-
./spec/ruby_llm/chat_tools_spec.rb[1:1:7] | passed | 2.71 seconds |
|
31
|
-
./spec/ruby_llm/chat_tools_spec.rb[1:1:8] | passed | 4 seconds |
|
32
|
-
./spec/ruby_llm/chat_tools_spec.rb[1:1:9] | passed | 2.81 seconds |
|
33
|
-
./spec/ruby_llm/embeddings_spec.rb[1:1:1:1] | passed | 0.33357 seconds |
|
34
|
-
./spec/ruby_llm/embeddings_spec.rb[1:1:1:2] | passed | 0.43632 seconds |
|
35
|
-
./spec/ruby_llm/embeddings_spec.rb[1:1:2:1] | passed | 0.65614 seconds |
|
36
|
-
./spec/ruby_llm/embeddings_spec.rb[1:1:2:2] | passed | 2.16 seconds |
|
37
|
-
./spec/ruby_llm/error_handling_spec.rb[1:1] | passed | 0.29366 seconds |
|
38
|
-
./spec/ruby_llm/image_generation_spec.rb[1:1:1] | passed | 14.16 seconds |
|
39
|
-
./spec/ruby_llm/image_generation_spec.rb[1:1:2] | passed | 16.22 seconds |
|
40
|
-
./spec/ruby_llm/image_generation_spec.rb[1:1:3] | passed | 9.1 seconds |
|
41
|
-
./spec/ruby_llm/image_generation_spec.rb[1:1:4] | passed | 0.00138 seconds |
|
42
|
-
./spec/ruby_llm/models_spec.rb[1:1:1] | passed | 0.01071 seconds |
|
43
|
-
./spec/ruby_llm/models_spec.rb[1:1:2] | passed | 0.00056 seconds |
|
44
|
-
./spec/ruby_llm/models_spec.rb[1:1:3] | passed | 0.00336 seconds |
|
45
|
-
./spec/ruby_llm/models_spec.rb[1:2:1] | passed | 0.00016 seconds |
|
46
|
-
./spec/ruby_llm/models_spec.rb[1:2:2] | passed | 0.00085 seconds |
|
47
|
-
./spec/ruby_llm/models_spec.rb[1:3:1] | passed | 1.44 seconds |
|
48
|
-
./spec/ruby_llm/models_spec.rb[1:3:2] | passed | 1.23 seconds |
|
49
|
-
./spec/ruby_llm/models_spec.rb[1:4:1] | passed | 0.0003 seconds |
|
50
|
-
./spec/ruby_llm/models_spec.rb[1:4:2] | passed | 0.00175 seconds |
|