ragnar-cli 0.1.0.pre.3 → 0.1.0.pre.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 +4 -4
- data/README.md +187 -36
- data/lib/ragnar/cli.rb +527 -172
- data/lib/ragnar/cli_visualization.rb +184 -0
- data/lib/ragnar/config.rb +226 -0
- data/lib/ragnar/database.rb +94 -8
- data/lib/ragnar/llm_manager.rb +4 -1
- data/lib/ragnar/query_processor.rb +38 -20
- data/lib/ragnar/topic_modeling.rb +13 -10
- data/lib/ragnar/umap_processor.rb +77 -65
- data/lib/ragnar/umap_transform_service.rb +169 -88
- data/lib/ragnar/version.rb +1 -1
- metadata +43 -22
- data/lib/ragnar/topic_modeling/engine.rb +0 -301
- data/lib/ragnar/topic_modeling/labeling_strategies.rb +0 -300
- data/lib/ragnar/topic_modeling/llm_adapter.rb +0 -131
- data/lib/ragnar/topic_modeling/metrics.rb +0 -186
- data/lib/ragnar/topic_modeling/term_extractor.rb +0 -170
- data/lib/ragnar/topic_modeling/topic.rb +0 -117
- data/lib/ragnar/topic_modeling/topic_labeler.rb +0 -61
@@ -1,24 +1,27 @@
|
|
1
|
-
#
|
2
|
-
# Designed for future extraction into a separate gem
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
require_relative 'topic_modeling/engine'
|
3
|
+
# Topic modeling wrapper that delegates to the Topical gem
|
4
|
+
# This maintains backward compatibility while using the extracted library
|
5
|
+
|
6
|
+
require 'topical'
|
9
7
|
|
10
8
|
module Ragnar
|
11
9
|
module TopicModeling
|
10
|
+
# Re-export Topical classes for backward compatibility
|
11
|
+
Topic = Topical::Topic
|
12
|
+
Engine = Topical::Engine
|
13
|
+
|
14
|
+
# Re-export metrics module
|
15
|
+
Metrics = Topical::Metrics
|
12
16
|
|
13
17
|
# Convenience method to create a new topic modeling engine
|
14
18
|
def self.new(**options)
|
15
|
-
Engine.new(**options)
|
19
|
+
Topical::Engine.new(**options)
|
16
20
|
end
|
17
21
|
|
18
22
|
# Extract topics from embeddings and documents (simple interface)
|
19
23
|
def self.extract(embeddings:, documents:, **options)
|
20
|
-
|
21
|
-
engine.fit(embeddings: embeddings, documents: documents)
|
24
|
+
Topical.extract(embeddings: embeddings, documents: documents, **options)
|
22
25
|
end
|
23
26
|
end
|
24
27
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'json'
|
2
|
+
require 'time'
|
2
3
|
|
3
4
|
module Ragnar
|
4
5
|
class UmapProcessor
|
@@ -196,10 +197,10 @@ module Ragnar
|
|
196
197
|
end
|
197
198
|
|
198
199
|
def apply(batch_size: 100)
|
199
|
-
# Load the trained UMAP model
|
200
|
-
|
200
|
+
# Load the trained UMAP model
|
201
|
+
umap_model = load_umap_model
|
201
202
|
|
202
|
-
puts "Applying
|
203
|
+
puts "Applying UMAP transformation to database documents..."
|
203
204
|
|
204
205
|
# Get all embeddings from database
|
205
206
|
all_docs = @database.get_embeddings
|
@@ -214,84 +215,95 @@ module Ragnar
|
|
214
215
|
end
|
215
216
|
|
216
217
|
puts "Found #{all_docs.size} documents in database"
|
217
|
-
puts "Loaded #{reduced_embeddings.size} reduced embeddings from model"
|
218
218
|
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
219
|
+
# Process in batches for memory efficiency
|
220
|
+
processed_count = 0
|
221
|
+
error_count = 0
|
222
|
+
skipped_count = 0
|
223
|
+
|
224
|
+
all_docs.each_slice(batch_size) do |batch|
|
225
|
+
begin
|
226
|
+
# Extract embeddings
|
227
|
+
embeddings = batch.map { |d| d[:embedding] }
|
228
|
+
|
229
|
+
# Validate embeddings
|
230
|
+
valid_indices = []
|
231
|
+
embeddings_to_transform = []
|
232
|
+
|
233
|
+
embeddings.each_with_index do |emb, idx|
|
234
|
+
if emb.nil? || !emb.is_a?(Array) || emb.empty?
|
235
|
+
skipped_count += 1
|
236
|
+
next
|
237
|
+
end
|
238
|
+
|
239
|
+
if emb.any? { |v| !v.is_a?(Numeric) || v.nan? || !v.finite? }
|
240
|
+
skipped_count += 1
|
241
|
+
next
|
242
|
+
end
|
243
|
+
|
244
|
+
valid_indices << idx
|
245
|
+
embeddings_to_transform << emb
|
246
|
+
end
|
247
|
+
|
248
|
+
next if embeddings_to_transform.empty?
|
249
|
+
|
250
|
+
# Transform using the loaded UMAP model
|
251
|
+
reduced_embeddings = umap_model.transform(embeddings_to_transform)
|
252
|
+
|
253
|
+
# Prepare updates for valid documents
|
254
|
+
updates = valid_indices.map.with_index do |batch_idx, transform_idx|
|
255
|
+
{
|
256
|
+
id: batch[batch_idx][:id],
|
257
|
+
reduced_embedding: reduced_embeddings[transform_idx]
|
258
|
+
}
|
259
|
+
end
|
260
|
+
|
261
|
+
# Update database
|
262
|
+
@database.update_reduced_embeddings(updates)
|
263
|
+
processed_count += updates.size
|
264
|
+
|
265
|
+
puts " Processed batch: #{updates.size} documents transformed"
|
266
|
+
rescue => e
|
267
|
+
puts " ⚠️ Error processing batch: #{e.message}"
|
268
|
+
error_count += batch.size
|
269
|
+
end
|
236
270
|
end
|
237
271
|
|
238
|
-
puts "
|
239
|
-
|
272
|
+
puts "\nUMAP application complete:"
|
273
|
+
puts " ✓ Processed: #{processed_count} documents"
|
274
|
+
puts " ⚠️ Skipped: #{skipped_count} documents (invalid embeddings)" if skipped_count > 0
|
275
|
+
puts " ❌ Errors: #{error_count} documents" if error_count > 0
|
240
276
|
|
241
277
|
{
|
242
|
-
processed:
|
243
|
-
skipped:
|
244
|
-
errors:
|
278
|
+
processed: processed_count,
|
279
|
+
skipped: skipped_count,
|
280
|
+
errors: error_count
|
245
281
|
}
|
246
282
|
end
|
247
283
|
|
248
284
|
private
|
249
285
|
|
250
|
-
def process_batch(docs)
|
251
|
-
# Extract embeddings
|
252
|
-
embeddings = docs.map { |d| d[:embedding] }
|
253
|
-
|
254
|
-
# Transform using UMAP
|
255
|
-
# The transform method returns a 2D array where each row is a reduced embedding
|
256
|
-
reduced = @umap_model.transform(embeddings)
|
257
|
-
|
258
|
-
# Prepare updates
|
259
|
-
updates = docs.each_with_index.map do |doc, idx|
|
260
|
-
{
|
261
|
-
id: doc[:id],
|
262
|
-
reduced_embedding: reduced[idx]
|
263
|
-
}
|
264
|
-
end
|
265
|
-
|
266
|
-
# Update database
|
267
|
-
@database.update_reduced_embeddings(updates)
|
268
|
-
end
|
269
|
-
|
270
286
|
def save_model
|
271
|
-
return unless @umap_instance
|
287
|
+
return unless @umap_instance
|
272
288
|
|
273
|
-
# Save the trained UMAP model for transforming new
|
289
|
+
# Save the trained UMAP model for transforming new data
|
274
290
|
@umap_instance.save_model(@model_path)
|
275
291
|
puts "UMAP model saved to: #{@model_path}"
|
276
292
|
|
277
|
-
#
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
293
|
+
# Save metadata about the training if we have params
|
294
|
+
if @model_params
|
295
|
+
metadata_path = @model_path.sub(/\.bin$/, '_metadata.json')
|
296
|
+
metadata = {
|
297
|
+
trained_at: Time.now.iso8601,
|
298
|
+
n_components: @model_params[:n_components],
|
299
|
+
n_neighbors: @model_params[:n_neighbors],
|
300
|
+
min_dist: @model_params[:min_dist],
|
301
|
+
document_count: @database.get_embeddings.size,
|
302
|
+
model_version: 2 # Version 2: proper transform-based approach
|
303
|
+
}
|
304
|
+
File.write(metadata_path, JSON.pretty_generate(metadata))
|
305
|
+
puts "Model metadata saved to: #{metadata_path}"
|
290
306
|
end
|
291
|
-
|
292
|
-
@reduced_embeddings = ClusterKit::Dimensionality::UMAP.load_data(embeddings_path)
|
293
|
-
puts "Cached embeddings loaded from: #{embeddings_path}"
|
294
|
-
@reduced_embeddings
|
295
307
|
end
|
296
308
|
|
297
309
|
def load_umap_model
|
@@ -1,124 +1,205 @@
|
|
1
|
+
require 'json'
|
1
2
|
require 'clusterkit'
|
2
3
|
|
3
4
|
module Ragnar
|
5
|
+
# Service for applying UMAP transformations to embeddings
|
6
|
+
# Separates transformation logic from training (UmapProcessor)
|
4
7
|
class UmapTransformService
|
5
|
-
|
8
|
+
attr_reader :model_path, :database
|
6
9
|
|
7
|
-
def initialize
|
10
|
+
def initialize(model_path: "umap_model.bin", database:)
|
11
|
+
@model_path = model_path
|
12
|
+
@database = database
|
8
13
|
@umap_model = nil
|
9
|
-
@
|
14
|
+
@model_metadata = nil
|
10
15
|
end
|
11
16
|
|
12
|
-
# Transform
|
13
|
-
|
14
|
-
|
15
|
-
|
17
|
+
# Transform embeddings for specific documents
|
18
|
+
# @param document_ids [Array<Integer>] IDs of documents to transform
|
19
|
+
# @return [Hash] Results with :processed, :skipped, :errors counts
|
20
|
+
def transform_documents(document_ids)
|
21
|
+
return { processed: 0, skipped: 0, errors: 0 } if document_ids.empty?
|
16
22
|
|
17
|
-
|
18
|
-
load_model(model_path) unless @umap_model
|
23
|
+
load_model!
|
19
24
|
|
20
|
-
#
|
21
|
-
|
22
|
-
result = @umap_model.transform([query_embedding])
|
25
|
+
# Fetch documents
|
26
|
+
documents = @database.get_documents_by_ids(document_ids)
|
23
27
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
# Fall back to k-NN approximation if model loading fails
|
28
|
-
puts "Warning: Could not use UMAP model for transform: #{e.message}"
|
29
|
-
puts "Falling back to k-NN approximation..."
|
30
|
-
knn_approximate_transform(query_embedding)
|
31
|
-
end
|
32
|
-
|
33
|
-
# Check if we can do transforms
|
34
|
-
def model_available?(model_path = nil)
|
35
|
-
model_path ||= @model_path
|
28
|
+
if documents.empty?
|
29
|
+
return { processed: 0, skipped: 0, errors: 0 }
|
30
|
+
end
|
36
31
|
|
37
|
-
#
|
38
|
-
|
39
|
-
|
32
|
+
# Extract and validate embeddings
|
33
|
+
valid_docs = []
|
34
|
+
embeddings_to_transform = []
|
35
|
+
skipped_count = 0
|
36
|
+
|
37
|
+
documents.each do |doc|
|
38
|
+
emb = doc[:embedding]
|
39
|
+
|
40
|
+
if emb.nil? || !emb.is_a?(Array) || emb.empty?
|
41
|
+
skipped_count += 1
|
42
|
+
next
|
43
|
+
end
|
44
|
+
|
45
|
+
if emb.any? { |v| !v.is_a?(Numeric) || v.nan? || !v.finite? }
|
46
|
+
skipped_count += 1
|
47
|
+
next
|
48
|
+
end
|
49
|
+
|
50
|
+
valid_docs << doc
|
51
|
+
embeddings_to_transform << emb
|
40
52
|
end
|
41
53
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
54
|
+
return { processed: 0, skipped: skipped_count, errors: 0 } if embeddings_to_transform.empty?
|
55
|
+
|
56
|
+
# Transform using UMAP
|
57
|
+
begin
|
58
|
+
reduced_embeddings = @umap_model.transform(embeddings_to_transform)
|
59
|
+
|
60
|
+
# Prepare updates
|
61
|
+
updates = valid_docs.zip(reduced_embeddings).map do |doc, reduced_emb|
|
62
|
+
{
|
63
|
+
id: doc[:id],
|
64
|
+
reduced_embedding: reduced_emb,
|
65
|
+
umap_version: model_version
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
69
|
+
# Update database
|
70
|
+
@database.update_reduced_embeddings(updates)
|
71
|
+
|
72
|
+
{ processed: updates.size, skipped: skipped_count, errors: 0 }
|
73
|
+
rescue => e
|
74
|
+
puts "Error transforming documents: #{e.message}"
|
75
|
+
{ processed: 0, skipped: skipped_count, errors: valid_docs.size }
|
76
|
+
end
|
46
77
|
end
|
47
78
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
79
|
+
# Transform a single query embedding
|
80
|
+
# @param embedding [Array<Numeric>] Query embedding to transform
|
81
|
+
# @return [Array<Float>, nil] Reduced embedding or nil if error
|
82
|
+
def transform_query(embedding)
|
83
|
+
return nil if embedding.nil? || !embedding.is_a?(Array) || embedding.empty?
|
84
|
+
|
85
|
+
# Validate embedding
|
86
|
+
if embedding.any? { |v| !v.is_a?(Numeric) || v.nan? || !v.finite? }
|
87
|
+
puts "Warning: Invalid query embedding (contains NaN or Infinity)"
|
88
|
+
return nil
|
53
89
|
end
|
54
90
|
|
55
|
-
|
56
|
-
|
91
|
+
load_model!
|
92
|
+
|
93
|
+
begin
|
94
|
+
# Transform returns array of arrays, get first (and only) result
|
95
|
+
@umap_model.transform([embedding]).first
|
96
|
+
rescue => e
|
97
|
+
puts "Error transforming query: #{e.message}"
|
98
|
+
nil
|
99
|
+
end
|
57
100
|
end
|
58
101
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
102
|
+
# Check if a UMAP model exists
|
103
|
+
# @return [Boolean] true if model file exists
|
104
|
+
def model_exists?
|
105
|
+
File.exist?(@model_path)
|
106
|
+
end
|
107
|
+
|
108
|
+
# Get metadata about the trained model
|
109
|
+
# @return [Hash, nil] Model metadata or nil if not found
|
110
|
+
def model_metadata
|
111
|
+
return @model_metadata if @model_metadata
|
69
112
|
|
70
|
-
|
71
|
-
|
113
|
+
metadata_path = @model_path.sub(/\.bin$/, '_metadata.json')
|
114
|
+
return nil unless File.exist?(metadata_path)
|
72
115
|
|
73
|
-
|
74
|
-
|
75
|
-
|
116
|
+
@model_metadata = JSON.parse(File.read(metadata_path), symbolize_names: true)
|
117
|
+
rescue => e
|
118
|
+
puts "Error loading model metadata: #{e.message}"
|
119
|
+
nil
|
120
|
+
end
|
121
|
+
|
122
|
+
# Get the version of the current model
|
123
|
+
# @return [Integer] Model version (timestamp of file modification)
|
124
|
+
def model_version
|
125
|
+
return 0 unless File.exist?(@model_path)
|
126
|
+
File.mtime(@model_path).to_i
|
127
|
+
end
|
128
|
+
|
129
|
+
# Check if model needs retraining based on staleness
|
130
|
+
# @return [Hash] Staleness info with :needs_retraining, :coverage_percentage
|
131
|
+
def check_model_staleness
|
132
|
+
return { needs_retraining: true, coverage_percentage: 0, reason: "No model exists" } unless model_exists?
|
76
133
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
distance = euclidean_distance(query_embedding, doc[:embedding])
|
81
|
-
neighbors << { idx: idx, distance: distance, reduced: doc[:reduced_embedding] }
|
82
|
-
end
|
134
|
+
metadata = model_metadata
|
135
|
+
return { needs_retraining: true, coverage_percentage: 0, reason: "No metadata found" } unless metadata
|
83
136
|
|
84
|
-
|
85
|
-
|
86
|
-
k_nearest = neighbors.first(k)
|
137
|
+
trained_count = metadata[:document_count] || 0
|
138
|
+
current_count = @database.document_count
|
87
139
|
|
88
|
-
|
89
|
-
|
90
|
-
if k_nearest.empty?
|
91
|
-
raise "No neighbors found for transform"
|
140
|
+
if current_count == 0
|
141
|
+
return { needs_retraining: false, coverage_percentage: 100, reason: "No documents" }
|
92
142
|
end
|
93
143
|
|
94
|
-
|
95
|
-
|
144
|
+
coverage = (trained_count.to_f / current_count * 100).round(1)
|
145
|
+
staleness = 100 - coverage
|
146
|
+
|
147
|
+
{
|
148
|
+
needs_retraining: staleness > 30,
|
149
|
+
coverage_percentage: coverage,
|
150
|
+
trained_documents: trained_count,
|
151
|
+
current_documents: current_count,
|
152
|
+
staleness_percentage: staleness,
|
153
|
+
reason: staleness > 30 ? "Model covers only #{coverage}% of documents" : "Model is up to date"
|
154
|
+
}
|
155
|
+
end
|
156
|
+
|
157
|
+
private
|
158
|
+
|
159
|
+
def load_model!
|
160
|
+
return if @umap_model
|
96
161
|
|
97
|
-
|
98
|
-
|
99
|
-
k_nearest.each do |neighbor|
|
100
|
-
# Use inverse distance as weight (closer = higher weight)
|
101
|
-
weight = 1.0 / (neighbor[:distance] + 0.001) # Add small epsilon to avoid division by zero
|
102
|
-
total_weight += weight
|
103
|
-
|
104
|
-
neighbor[:reduced].each_with_index do |val, idx|
|
105
|
-
averaged[idx] += val * weight
|
106
|
-
end
|
162
|
+
unless File.exist?(@model_path)
|
163
|
+
raise "UMAP model not found at #{@model_path}. Please train a model first using 'ragnar train-umap'."
|
107
164
|
end
|
108
165
|
|
109
|
-
|
110
|
-
averaged.map { |val| val / total_weight }
|
166
|
+
@umap_model = ClusterKit::Dimensionality::UMAP.load_model(@model_path)
|
111
167
|
end
|
168
|
+
end
|
169
|
+
|
170
|
+
# Singleton service for backwards compatibility
|
171
|
+
# This allows the old UmapTransformService.instance pattern to work
|
172
|
+
class UmapTransformServiceSingleton
|
173
|
+
include Singleton
|
112
174
|
|
113
|
-
def
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
175
|
+
def initialize
|
176
|
+
@database = Database.new(Config.instance.database_path)
|
177
|
+
@service = UmapTransformService.new(database: @database)
|
178
|
+
end
|
179
|
+
|
180
|
+
def transform_query(embedding, model_path = nil)
|
181
|
+
if model_path && model_path != @service.model_path
|
182
|
+
# Create a new service with different model path
|
183
|
+
service = UmapTransformService.new(model_path: model_path, database: @database)
|
184
|
+
service.transform_query(embedding)
|
185
|
+
else
|
186
|
+
@service.transform_query(embedding)
|
120
187
|
end
|
121
|
-
|
188
|
+
end
|
189
|
+
|
190
|
+
def model_available?(model_path = nil)
|
191
|
+
if model_path
|
192
|
+
File.exist?(model_path)
|
193
|
+
else
|
194
|
+
@service.model_exists?
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
# For backwards compatibility - old code uses UmapTransformService.instance
|
200
|
+
class << UmapTransformService
|
201
|
+
def instance
|
202
|
+
UmapTransformServiceSingleton.instance
|
122
203
|
end
|
123
204
|
end
|
124
205
|
end
|
data/lib/ragnar/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ragnar-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.0.pre.
|
4
|
+
version: 0.1.0.pre.4
|
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-08
|
11
|
+
date: 2025-09-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 1.2.3
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 1.2.3
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: lancelot
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -47,7 +47,7 @@ dependencies:
|
|
47
47
|
version: '0.3'
|
48
48
|
- - ">="
|
49
49
|
- !ruby/object:Gem::Version
|
50
|
-
version: 0.3.
|
50
|
+
version: 0.3.3
|
51
51
|
type: :runtime
|
52
52
|
prerelease: false
|
53
53
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -57,21 +57,27 @@ dependencies:
|
|
57
57
|
version: '0.3'
|
58
58
|
- - ">="
|
59
59
|
- !ruby/object:Gem::Version
|
60
|
-
version: 0.3.
|
60
|
+
version: 0.3.3
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
|
-
name:
|
62
|
+
name: topical
|
63
63
|
requirement: !ruby/object:Gem::Requirement
|
64
64
|
requirements:
|
65
65
|
- - "~>"
|
66
66
|
- !ruby/object:Gem::Version
|
67
|
-
version: 0.1.0
|
67
|
+
version: 0.1.0
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: 0.1.1
|
68
71
|
type: :runtime
|
69
72
|
prerelease: false
|
70
73
|
version_requirements: !ruby/object:Gem::Requirement
|
71
74
|
requirements:
|
72
75
|
- - "~>"
|
73
76
|
- !ruby/object:Gem::Version
|
74
|
-
version: 0.1.0
|
77
|
+
version: 0.1.0
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: 0.1.1
|
75
81
|
- !ruby/object:Gem::Dependency
|
76
82
|
name: baran
|
77
83
|
requirement: !ruby/object:Gem::Requirement
|
@@ -92,14 +98,20 @@ dependencies:
|
|
92
98
|
requirements:
|
93
99
|
- - "~>"
|
94
100
|
- !ruby/object:Gem::Version
|
95
|
-
version: 0.1
|
101
|
+
version: '0.1'
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: 0.1.2
|
96
105
|
type: :runtime
|
97
106
|
prerelease: false
|
98
107
|
version_requirements: !ruby/object:Gem::Requirement
|
99
108
|
requirements:
|
100
109
|
- - "~>"
|
101
110
|
- !ruby/object:Gem::Version
|
102
|
-
version: 0.1
|
111
|
+
version: '0.1'
|
112
|
+
- - ">="
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: 0.1.2
|
103
115
|
- !ruby/object:Gem::Dependency
|
104
116
|
name: tty-progressbar
|
105
117
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,6 +126,20 @@ dependencies:
|
|
114
126
|
- - "~>"
|
115
127
|
- !ruby/object:Gem::Version
|
116
128
|
version: '0.18'
|
129
|
+
- !ruby/object:Gem::Dependency
|
130
|
+
name: thor-interactive
|
131
|
+
requirement: !ruby/object:Gem::Requirement
|
132
|
+
requirements:
|
133
|
+
- - "~>"
|
134
|
+
- !ruby/object:Gem::Version
|
135
|
+
version: 0.1.0.pre.3
|
136
|
+
type: :runtime
|
137
|
+
prerelease: false
|
138
|
+
version_requirements: !ruby/object:Gem::Requirement
|
139
|
+
requirements:
|
140
|
+
- - "~>"
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: 0.1.0.pre.3
|
117
143
|
- !ruby/object:Gem::Dependency
|
118
144
|
name: rake
|
119
145
|
requirement: !ruby/object:Gem::Requirement
|
@@ -186,6 +212,8 @@ files:
|
|
186
212
|
- lib/ragnar.rb
|
187
213
|
- lib/ragnar/chunker.rb
|
188
214
|
- lib/ragnar/cli.rb
|
215
|
+
- lib/ragnar/cli_visualization.rb
|
216
|
+
- lib/ragnar/config.rb
|
189
217
|
- lib/ragnar/context_repacker.rb
|
190
218
|
- lib/ragnar/database.rb
|
191
219
|
- lib/ragnar/embedder.rb
|
@@ -194,24 +222,17 @@ files:
|
|
194
222
|
- lib/ragnar/query_processor.rb
|
195
223
|
- lib/ragnar/query_rewriter.rb
|
196
224
|
- lib/ragnar/topic_modeling.rb
|
197
|
-
- lib/ragnar/topic_modeling/engine.rb
|
198
|
-
- lib/ragnar/topic_modeling/labeling_strategies.rb
|
199
|
-
- lib/ragnar/topic_modeling/llm_adapter.rb
|
200
|
-
- lib/ragnar/topic_modeling/metrics.rb
|
201
|
-
- lib/ragnar/topic_modeling/term_extractor.rb
|
202
|
-
- lib/ragnar/topic_modeling/topic.rb
|
203
|
-
- lib/ragnar/topic_modeling/topic_labeler.rb
|
204
225
|
- lib/ragnar/umap_processor.rb
|
205
226
|
- lib/ragnar/umap_transform_service.rb
|
206
227
|
- lib/ragnar/version.rb
|
207
228
|
- lib/ragnar_cli.rb
|
208
|
-
homepage: https://github.com/
|
229
|
+
homepage: https://github.com/scientist-labs/ragnar
|
209
230
|
licenses:
|
210
231
|
- MIT
|
211
232
|
metadata:
|
212
|
-
homepage_uri: https://github.com/
|
213
|
-
source_code_uri: https://github.com/
|
214
|
-
changelog_uri: https://github.com/
|
233
|
+
homepage_uri: https://github.com/scientist-labs/ragnar
|
234
|
+
source_code_uri: https://github.com/scientist-labs/ragnar
|
235
|
+
changelog_uri: https://github.com/scientist-labs/ragnar/blob/main/CHANGELOG.md
|
215
236
|
post_install_message:
|
216
237
|
rdoc_options: []
|
217
238
|
require_paths:
|