ruby_llm-red_candle 0.1.0 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c6a9af49d55182783c1cebd1e02748f3a9e0716a8e35bb87e250c38075731784
4
- data.tar.gz: 32242fd560276ce4889ea640ffebc11c81f0e4f1afef83e7edfe5204cdb813ce
3
+ metadata.gz: 3d28e7533552659e4618c7774c7758741d49433dfd320b0a483a0e93dfd20889
4
+ data.tar.gz: 7da03bf5b36d20608917f261b2ec284a6e4dd50bba9a95ebbbfa618f149a2948
5
5
  SHA512:
6
- metadata.gz: 6c28f204a8faedfda2c578ec9a05227a36c69047e7bd31555e9603fae6ad5c86b9b4680ba2119af70e49d80f6705d9d1c5bd7b9290e6acda7042beb9102bf714
7
- data.tar.gz: 40411b9e81a77b97a0dcb1a5dd01e9b5ef5d7b6d0a3cf3c211a72b8879f1985a9b129cdf384bc72077d48c0b9bef66ed6a83730ee3803adeec72b21dbe33db83
6
+ metadata.gz: c05f230c8f8cc3d42b0ce4194f1d67d3964424a421b29745d3d8ebfeba1499b0e4a7452d8349a6940ba62139b745181e0b63f99a2a43cd68fce2ff4241bdbaf8
7
+ data.tar.gz: 0ed7589883dcd93fe699fc2f702563dbac6905a72309c13d7fb98042ec4189e3dac1827e6e016411856378544e6c4cbe5f8f0b14087541732e86c7da0c01a2c6
@@ -11,7 +11,7 @@ module RubyLLM
11
11
  end
12
12
 
13
13
  def supports_functions?(_model_id = nil)
14
- false
14
+ true
15
15
  end
16
16
 
17
17
  def supports_streaming?
@@ -5,8 +5,10 @@ module RubyLLM
5
5
  # Chat implementation for Red Candle provider
6
6
  module Chat
7
7
  # Override the base complete method to handle local execution
8
- def complete(messages, tools:, temperature:, model:, params: {}, headers: {}, schema: nil, &block)
8
+ def complete(messages, tools:, temperature:, model:, params: {}, headers: {}, schema: nil, tool_prefs: nil, thinking: nil, &block)
9
9
  _ = headers # Interface compatibility
10
+ _ = tool_prefs # Interface compatibility (not yet used by local models)
11
+ _ = thinking # Interface compatibility (not yet used by local models)
10
12
  payload = RubyLLM::Utils.deep_merge(
11
13
  render_payload(
12
14
  messages,
@@ -23,11 +25,13 @@ module RubyLLM
23
25
  perform_streaming_completion!(payload, &block)
24
26
  else
25
27
  result = perform_completion!(payload)
26
- # Convert to Message object for compatibility
27
- # Red Candle doesn't provide token counts by default, but we can estimate them
28
+
29
+ # perform_tool_completion! returns a Message directly
30
+ return result if result.is_a?(RubyLLM::Message)
31
+
32
+ # Convert hash result to Message object
28
33
  content = result[:content]
29
- # Rough estimation: ~4 characters per token
30
- estimated_output_tokens = (content.length / 4.0).round
34
+ estimated_output_tokens = (content.to_s.length / 4.0).round
31
35
  estimated_input_tokens = estimate_input_tokens(payload[:messages])
32
36
 
33
37
  RubyLLM::Message.new(
@@ -40,25 +44,31 @@ module RubyLLM
40
44
  end
41
45
  end
42
46
 
43
- def render_payload(messages, tools:, temperature:, model:, stream:, schema:)
44
- # Red Candle doesn't support tools
45
- if tools && !tools.empty?
46
- raise RubyLLM::Error.new(nil, "Red Candle provider does not support tool calling")
47
- end
48
-
49
- {
47
+ def render_payload(messages, tools:, temperature:, model:, stream:, schema:, tool_prefs: nil, thinking: nil)
48
+ payload = {
50
49
  messages: messages,
51
50
  temperature: temperature,
52
51
  model: model.id,
53
52
  stream: stream,
54
53
  schema: schema
55
54
  }
55
+
56
+ if tools && !tools.empty?
57
+ payload[:tools] = tools
58
+ end
59
+
60
+ payload
56
61
  end
57
62
 
58
63
  def perform_completion!(payload)
59
64
  model = ensure_model_loaded!(payload[:model])
60
65
  messages = format_messages(payload[:messages])
61
66
 
67
+ # Handle tool calling
68
+ if payload[:tools] && !payload[:tools].empty?
69
+ return perform_tool_completion!(model, messages, payload)
70
+ end
71
+
62
72
  # Handle structured generation differently - we need to build the prompt
63
73
  # with JSON instructions BEFORE applying the chat template
64
74
  response = if payload[:schema]
@@ -110,6 +120,34 @@ module RubyLLM
110
120
 
111
121
  private
112
122
 
123
+ def perform_tool_completion!(model, messages, payload)
124
+ # Convert RubyLLM tools to Candle tools
125
+ candle_tools = payload[:tools].values.map { |t| Tools.candle_tool_for(t) }
126
+
127
+ # Build generation config with enough room for thinking + tool calls
128
+ # Tool calling needs more tokens than regular chat (model uses <think> blocks)
129
+ payload[:max_tokens] ||= 1000
130
+ config = build_generation_config(payload)
131
+
132
+ # Use red-candle's chat_with_tools (execute: false — RubyLLM manages execution)
133
+ result = model.chat_with_tools(messages, tools: candle_tools, config: config)
134
+
135
+ content = result.text_response || ""
136
+ tool_calls = Tools.parse_tool_calls(result.tool_calls)
137
+
138
+ estimated_output_tokens = ((result.raw_response || "").length / 4.0).round
139
+ estimated_input_tokens = estimate_input_tokens(payload[:messages])
140
+
141
+ RubyLLM::Message.new(
142
+ role: :assistant,
143
+ content: content.empty? ? nil : content,
144
+ tool_calls: tool_calls,
145
+ model_id: payload[:model],
146
+ input_tokens: estimated_input_tokens,
147
+ output_tokens: estimated_output_tokens
148
+ )
149
+ end
150
+
113
151
  # Build the prompt string from messages using the model's chat template
114
152
  def build_prompt(model, messages)
115
153
  if model.respond_to?(:apply_chat_template)
@@ -229,12 +267,17 @@ module RubyLLM
229
267
 
230
268
  def format_messages(messages)
231
269
  messages.map do |msg|
232
- # Handle both hash and Message objects
233
270
  if msg.is_a?(RubyLLM::Message)
234
- {
235
- role: msg.role.to_s,
236
- content: extract_message_content_from_object(msg)
237
- }
271
+ if msg.tool_call?
272
+ Tools.format_tool_call(msg)
273
+ elsif msg.tool_result?
274
+ Tools.format_tool_result(msg)
275
+ else
276
+ {
277
+ role: msg.role.to_s,
278
+ content: extract_message_content_from_object(msg)
279
+ }
280
+ end
238
281
  else
239
282
  {
240
283
  role: msg[:role].to_s,
@@ -292,8 +335,11 @@ module RubyLLM
292
335
  # Use Red Candle's native structured generation which uses the Rust outlines crate
293
336
  # for grammar-constrained generation. This ensures valid JSON output.
294
337
 
338
+ # Unwrap RubyLLM's schema wrapper format: {name: "response", schema: {...}, strict: true}
339
+ actual_schema = schema.is_a?(Hash) && (schema[:schema] || schema["schema"]) ? (schema[:schema] || schema["schema"]) : schema
340
+
295
341
  # Normalize schema to ensure consistent symbol keys
296
- normalized_schema = deep_symbolize_keys(schema)
342
+ normalized_schema = deep_symbolize_keys(actual_schema)
297
343
 
298
344
  # Validate schema before attempting generation
299
345
  SchemaValidator.validate!(normalized_schema)
@@ -6,14 +6,33 @@ module RubyLLM
6
6
  module Models
7
7
  # TODO: red-candle supports more models, but let's start with some well tested ones.
8
8
  SUPPORTED_MODELS = [
9
+ # Mistral
9
10
  {
10
- id: "google/gemma-3-4b-it-qat-q4_0-gguf",
11
- name: "Gemma 3 4B Instruct (Quantized)",
12
- gguf_file: "gemma-3-4b-it-q4_0.gguf",
13
- tokenizer: "google/gemma-3-4b-it", # Tokenizer from base model
14
- context_window: 8192,
15
- family: "gemma",
16
- architecture: "gemma2",
11
+ id: "TheBloke/Mistral-7B-Instruct-v0.2-GGUF",
12
+ name: "Mistral 7B Instruct v0.2 (Quantized)",
13
+ gguf_file: "mistral-7b-instruct-v0.2.Q4_K_M.gguf",
14
+ tokenizer: "mistralai/Mistral-7B-Instruct-v0.2",
15
+ context_window: 32_768,
16
+ family: "mistral",
17
+ supports_chat: true,
18
+ supports_structured: true
19
+ },
20
+ {
21
+ id: "MaziyarPanahi/Mistral-7B-Instruct-v0.3-GGUF",
22
+ name: "Mistral 7B Instruct v0.3 (Quantized)",
23
+ gguf_file: "Mistral-7B-Instruct-v0.3.Q4_K_M.gguf",
24
+ tokenizer: "mistralai/Mistral-7B-Instruct-v0.3",
25
+ context_window: 32_768,
26
+ family: "mistral",
27
+ supports_chat: true,
28
+ supports_structured: true
29
+ },
30
+ # Llama / TinyLlama
31
+ {
32
+ id: "TinyLlama/TinyLlama-1.1B-Chat-v1.0",
33
+ name: "TinyLlama 1.1B Chat",
34
+ context_window: 2048,
35
+ family: "llama",
17
36
  supports_chat: true,
18
37
  supports_structured: true
19
38
  },
@@ -23,28 +42,95 @@ module RubyLLM
23
42
  gguf_file: "tinyllama-1.1b-chat-v1.0.Q4_K_M.gguf",
24
43
  context_window: 2048,
25
44
  family: "llama",
26
- architecture: "llama",
27
45
  supports_chat: true,
28
46
  supports_structured: true
29
47
  },
48
+ # Gemma
30
49
  {
31
- id: "TheBloke/Mistral-7B-Instruct-v0.2-GGUF",
32
- name: "Mistral 7B Instruct v0.2 (Quantized)",
33
- gguf_file: "mistral-7b-instruct-v0.2.Q4_K_M.gguf",
34
- tokenizer: "mistralai/Mistral-7B-Instruct-v0.2",
35
- context_window: 32_768,
36
- family: "mistral",
37
- architecture: "mistral",
50
+ id: "google/gemma-3-4b-it-qat-q4_0-gguf",
51
+ name: "Gemma 3 4B Instruct (Quantized)",
52
+ gguf_file: "gemma-3-4b-it-q4_0.gguf",
53
+ tokenizer: "google/gemma-3-4b-it",
54
+ context_window: 8192,
55
+ family: "gemma",
38
56
  supports_chat: true,
39
57
  supports_structured: true
40
58
  },
59
+ # Qwen 2.5
41
60
  {
42
61
  id: "Qwen/Qwen2.5-1.5B-Instruct-GGUF",
43
62
  name: "Qwen 2.5 1.5B Instruct (Quantized)",
44
63
  gguf_file: "qwen2.5-1.5b-instruct-q4_k_m.gguf",
45
64
  context_window: 32_768,
46
65
  family: "qwen2",
47
- architecture: "qwen2",
66
+ supports_chat: true,
67
+ supports_structured: true
68
+ },
69
+ # Qwen 3
70
+ {
71
+ id: "Qwen/Qwen3-0.6B",
72
+ name: "Qwen3 0.6B",
73
+ context_window: 40_960,
74
+ family: "qwen3",
75
+ supports_chat: true,
76
+ supports_structured: true,
77
+ supports_tools: true
78
+ },
79
+ {
80
+ id: "MaziyarPanahi/Qwen3-0.6B-GGUF",
81
+ name: "Qwen3 0.6B (Quantized)",
82
+ gguf_file: "Qwen3-0.6B.Q4_K_M.gguf",
83
+ tokenizer: "Qwen/Qwen3-0.6B",
84
+ context_window: 40_960,
85
+ family: "qwen3",
86
+ supports_chat: true,
87
+ supports_structured: true,
88
+ supports_tools: true
89
+ },
90
+ {
91
+ id: "MaziyarPanahi/Qwen3-4B-GGUF",
92
+ name: "Qwen3 4B (Quantized)",
93
+ gguf_file: "Qwen3-4B.Q4_K_M.gguf",
94
+ tokenizer: "Qwen/Qwen3-4B",
95
+ context_window: 40_960,
96
+ family: "qwen3",
97
+ supports_chat: true,
98
+ supports_structured: true,
99
+ supports_tools: true
100
+ },
101
+ # SmolLM2
102
+ {
103
+ id: "HuggingFaceTB/SmolLM2-360M-Instruct",
104
+ name: "SmolLM2 360M Instruct",
105
+ context_window: 8192,
106
+ family: "llama",
107
+ supports_chat: true,
108
+ supports_structured: true
109
+ },
110
+ {
111
+ id: "HuggingFaceTB/SmolLM2-360M-Instruct-GGUF",
112
+ name: "SmolLM2 360M Instruct (Quantized)",
113
+ gguf_file: "smollm2-360m-instruct-q8_0.gguf",
114
+ context_window: 8192,
115
+ family: "llama",
116
+ supports_chat: true,
117
+ supports_structured: true
118
+ },
119
+ # Phi
120
+ {
121
+ id: "microsoft/phi-2",
122
+ name: "Phi 2",
123
+ context_window: 2048,
124
+ family: "phi",
125
+ supports_chat: true,
126
+ supports_structured: true
127
+ },
128
+ {
129
+ id: "TheBloke/phi-2-GGUF",
130
+ name: "Phi 2 (Quantized)",
131
+ gguf_file: "phi-2.Q4_K_M.gguf",
132
+ context_window: 2048,
133
+ family: "phi",
48
134
  supports_chat: true,
49
135
  supports_structured: true
50
136
  },
@@ -53,10 +139,66 @@ module RubyLLM
53
139
  name: "Phi 3 Mini 4K Instruct",
54
140
  context_window: 4096,
55
141
  family: "phi",
56
- architecture: "phi",
57
142
  supports_chat: true,
58
143
  supports_structured: true
59
- }
144
+ },
145
+ {
146
+ id: "microsoft/Phi-3-mini-4k-instruct-gguf",
147
+ name: "Phi 3 Mini 4K Instruct (Quantized)",
148
+ gguf_file: "Phi-3-mini-4k-instruct-q4.gguf",
149
+ context_window: 4096,
150
+ family: "phi",
151
+ supports_chat: true,
152
+ supports_structured: true
153
+ },
154
+ {
155
+ id: "microsoft/phi-4-gguf",
156
+ name: "Phi 4 (Quantized)",
157
+ gguf_file: "phi-4-Q4_K_S.gguf",
158
+ context_window: 16_384,
159
+ family: "phi",
160
+ supports_chat: true,
161
+ supports_structured: true
162
+ },
163
+ # Yi
164
+ {
165
+ id: "bartowski/Yi-1.5-6B-Chat-GGUF",
166
+ name: "Yi 1.5 6B Chat (Quantized)",
167
+ gguf_file: "Yi-1.5-6B-Chat-Q4_K_M.gguf",
168
+ tokenizer: "01-ai/Yi-1.5-6B-Chat",
169
+ context_window: 4096,
170
+ family: "llama",
171
+ supports_chat: true,
172
+ supports_structured: true
173
+ },
174
+ # Granite
175
+ {
176
+ id: "ibm-granite/granite-7b-instruct",
177
+ name: "Granite 7B Instruct",
178
+ context_window: 4096,
179
+ family: "granite",
180
+ supports_chat: true,
181
+ supports_structured: true
182
+ },
183
+ {
184
+ id: "ibm-granite/granite-4.0-micro",
185
+ name: "Granite 4.0 Micro",
186
+ context_window: 8192,
187
+ family: "granite",
188
+ supports_chat: true,
189
+ supports_structured: true
190
+ },
191
+ # GLM-4
192
+ {
193
+ id: "bartowski/THUDM_GLM-4-9B-0414-GGUF",
194
+ name: "GLM-4 9B (Quantized)",
195
+ gguf_file: "THUDM_GLM-4-9B-0414-Q4_K_M.gguf",
196
+ tokenizer: "THUDM/GLM-4-9B-0414",
197
+ context_window: 131_072,
198
+ family: "glm4",
199
+ supports_chat: true,
200
+ supports_structured: true
201
+ },
60
202
  ].freeze
61
203
 
62
204
  def list_models
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "securerandom"
4
+
5
+ module RubyLLM
6
+ module RedCandle
7
+ # Tool calling support for Red Candle provider.
8
+ # Bridges between RubyLLM::Tool and Candle::Tool formats.
9
+ module Tools
10
+ module_function
11
+
12
+ # Convert a RubyLLM::Tool to a Candle::Tool (without a callable block —
13
+ # RubyLLM manages tool execution itself)
14
+ def candle_tool_for(tool)
15
+ parameters = tool.params_schema ||
16
+ RubyLLM::Tool::SchemaDefinition.from_parameters(tool.parameters)&.json_schema ||
17
+ { type: "object", properties: {}, required: [] }
18
+
19
+ ::Candle::Tool.new(
20
+ name: tool.name,
21
+ description: tool.description || "",
22
+ parameters: parameters
23
+ ) { |_args| nil } # No-op block — RubyLLM handles execution
24
+ end
25
+
26
+ # Convert Candle::ToolCall objects to RubyLLM tool_calls hash format
27
+ # RubyLLM expects: { "call_id" => RubyLLM::ToolCall, ... }
28
+ def parse_tool_calls(candle_tool_calls)
29
+ return nil if candle_tool_calls.nil? || candle_tool_calls.empty?
30
+
31
+ tool_calls = {}
32
+ candle_tool_calls.each do |tc|
33
+ call_id = "call_#{SecureRandom.hex(12)}"
34
+ tool_calls[call_id] = RubyLLM::ToolCall.new(
35
+ id: call_id,
36
+ name: tc.name,
37
+ arguments: tc.arguments
38
+ )
39
+ end
40
+ tool_calls
41
+ end
42
+
43
+ # Format a tool call message (assistant message with tool_calls) for
44
+ # sending back to the model. Injects tool calls into the content.
45
+ def format_tool_call(msg)
46
+ content = msg.content.to_s
47
+ msg.tool_calls&.each_value do |tc|
48
+ content += "\n<tool_call>\n#{JSON.generate({ name: tc.name, arguments: tc.arguments })}\n</tool_call>"
49
+ end
50
+ { role: "assistant", content: content }
51
+ end
52
+
53
+ # Format a tool result message for sending back to the model
54
+ def format_tool_result(msg)
55
+ { role: "tool", content: msg.content.to_s }
56
+ end
57
+ end
58
+ end
59
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RubyLLM
4
4
  module RedCandle
5
- VERSION = "0.1.0"
5
+ VERSION = "0.2.0"
6
6
  end
7
7
  end
@@ -8,6 +8,7 @@ require_relative "ruby_llm/red_candle/schema_validator"
8
8
  require_relative "ruby_llm/red_candle/capabilities"
9
9
  require_relative "ruby_llm/red_candle/models"
10
10
  require_relative "ruby_llm/red_candle/streaming"
11
+ require_relative "ruby_llm/red_candle/tools"
11
12
  require_relative "ruby_llm/red_candle/chat"
12
13
  require_relative "ruby_llm/red_candle/provider"
13
14
 
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/ruby_llm/red_candle/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "ruby_llm-red_candle"
7
+ spec.version = RubyLLM::RedCandle::VERSION
8
+ spec.authors = ["Chris Petersen"]
9
+ spec.email = ["chris@scientist.com"]
10
+
11
+ spec.summary = "Red Candle provider for RubyLLM - local LLM execution using quantized GGUF models"
12
+ spec.description = <<~DESC
13
+ A RubyLLM plugin that enables local LLM execution using the Red Candle gem.
14
+ Run quantized GGUF models directly in Ruby without external API calls.
15
+ Supports streaming, structured output, and multiple model architectures
16
+ including Gemma, Llama, Qwen, Mistral, and Phi.
17
+ DESC
18
+ spec.homepage = "https://github.com/scientist-labs/ruby_llm-red_candle"
19
+ spec.license = "MIT"
20
+ spec.required_ruby_version = ">= 3.1.0"
21
+
22
+ spec.metadata["homepage_uri"] = spec.homepage
23
+ spec.metadata["source_code_uri"] = spec.homepage
24
+ spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/main/CHANGELOG.md"
25
+ spec.metadata["rubygems_mfa_required"] = "true"
26
+
27
+ # Specify which files should be added to the gem when it is released.
28
+ spec.files = Dir.chdir(__dir__) do
29
+ `git ls-files -z`.split("\x0").reject do |f|
30
+ (File.expand_path(f) == __FILE__) ||
31
+ f.start_with?(*%w[bin/ test/ spec/ features/ .git .github appveyor Gemfile])
32
+ end
33
+ end
34
+ spec.bindir = "exe"
35
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
36
+ spec.require_paths = ["lib"]
37
+
38
+ # Runtime dependencies
39
+ spec.add_dependency "ruby_llm", ">= 1.10", "< 3.0"
40
+ spec.add_dependency "red-candle", "~> 1.5"
41
+
42
+ # Development dependencies
43
+ spec.add_development_dependency "rake", "~> 13.0"
44
+ spec.add_development_dependency "rspec", "~> 3.12"
45
+ spec.add_development_dependency "rubocop", "~> 1.0"
46
+ spec.add_development_dependency "rubocop-rspec", "~> 3.0"
47
+ spec.add_development_dependency "simplecov", "~> 0.22"
48
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_llm-red_candle
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Petersen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-12-11 00:00:00.000000000 Z
11
+ date: 2026-03-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ruby_llm
@@ -16,7 +16,7 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '1.2'
19
+ version: '1.10'
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
22
  version: '3.0'
@@ -26,7 +26,7 @@ dependencies:
26
26
  requirements:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
- version: '1.2'
29
+ version: '1.10'
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
32
  version: '3.0'
@@ -36,14 +36,14 @@ dependencies:
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: '1.3'
39
+ version: '1.5'
40
40
  type: :runtime
41
41
  prerelease: false
42
42
  version_requirements: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
- version: '1.3'
46
+ version: '1.5'
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rake
49
49
  requirement: !ruby/object:Gem::Requirement
@@ -140,7 +140,9 @@ files:
140
140
  - lib/ruby_llm/red_candle/provider.rb
141
141
  - lib/ruby_llm/red_candle/schema_validator.rb
142
142
  - lib/ruby_llm/red_candle/streaming.rb
143
+ - lib/ruby_llm/red_candle/tools.rb
143
144
  - lib/ruby_llm/red_candle/version.rb
145
+ - ruby_llm-red_candle.gemspec
144
146
  homepage: https://github.com/scientist-labs/ruby_llm-red_candle
145
147
  licenses:
146
148
  - MIT
@@ -164,7 +166,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
164
166
  - !ruby/object:Gem::Version
165
167
  version: '0'
166
168
  requirements: []
167
- rubygems_version: 3.5.3
169
+ rubygems_version: 3.5.22
168
170
  signing_key:
169
171
  specification_version: 4
170
172
  summary: Red Candle provider for RubyLLM - local LLM execution using quantized GGUF