ragdoll-cli 0.0.2
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 +296 -0
- data/Rakefile +21 -0
- data/bin/ragdoll +7 -0
- data/lib/ragdoll/cli/commands/config.rb +152 -0
- data/lib/ragdoll/cli/commands/delete.rb +37 -0
- data/lib/ragdoll/cli/commands/health.rb +22 -0
- data/lib/ragdoll/cli/commands/list.rb +57 -0
- data/lib/ragdoll/cli/commands/search.rb +88 -0
- data/lib/ragdoll/cli/commands/stats.rb +44 -0
- data/lib/ragdoll/cli/commands/status.rb +35 -0
- data/lib/ragdoll/cli/commands/update.rb +33 -0
- data/lib/ragdoll/cli/configuration_loader.rb +144 -0
- data/lib/ragdoll/cli/standalone_client.rb +69 -0
- data/lib/ragdoll/cli/version.rb +8 -0
- data/lib/ragdoll/cli.rb +380 -0
- data/lib/tasks/annotate.rake +126 -0
- data/lib/tasks/db.rake +338 -0
- metadata +62 -0
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module Ragdoll
|
6
|
+
module CLI
|
7
|
+
class Stats
|
8
|
+
def call(options)
|
9
|
+
client = StandaloneClient.new
|
10
|
+
|
11
|
+
puts 'Retrieving system statistics'
|
12
|
+
puts "Options: #{options.to_h}" unless options.to_h.empty?
|
13
|
+
puts
|
14
|
+
|
15
|
+
stats = client.stats
|
16
|
+
|
17
|
+
if stats.nil? || stats.empty?
|
18
|
+
puts 'No statistics available.'
|
19
|
+
return
|
20
|
+
end
|
21
|
+
|
22
|
+
case options[:format]
|
23
|
+
when 'json'
|
24
|
+
puts JSON.pretty_generate(stats)
|
25
|
+
when 'plain'
|
26
|
+
stats.each do |key, value|
|
27
|
+
puts "#{key.to_s.tr('_', ' ').capitalize}: #{value}"
|
28
|
+
end
|
29
|
+
else
|
30
|
+
# Table format (default)
|
31
|
+
puts 'System Statistics:'
|
32
|
+
puts
|
33
|
+
puts 'Metric'.ljust(30) + 'Value'
|
34
|
+
puts '-' * 50
|
35
|
+
|
36
|
+
stats.each do |key, value|
|
37
|
+
metric = key.to_s.tr('_', ' ').capitalize.ljust(30)
|
38
|
+
puts "#{metric}#{value}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module Ragdoll
|
6
|
+
module CLI
|
7
|
+
class Status
|
8
|
+
def call(id, options)
|
9
|
+
client = StandaloneClient.new
|
10
|
+
|
11
|
+
puts "Checking status for document ID: #{id}"
|
12
|
+
puts "Options: #{options.to_h}" unless options.to_h.empty?
|
13
|
+
puts
|
14
|
+
|
15
|
+
status = client.document_status(id: id)
|
16
|
+
|
17
|
+
if status.nil? || status.empty?
|
18
|
+
puts 'Document not found or no status available.'
|
19
|
+
return
|
20
|
+
end
|
21
|
+
|
22
|
+
case options[:format]
|
23
|
+
when 'json'
|
24
|
+
puts JSON.pretty_generate(status)
|
25
|
+
else
|
26
|
+
puts "Document ID: #{id}"
|
27
|
+
puts "Status: #{status[:status] || 'N/A'}"
|
28
|
+
puts "Embeddings Count: #{status[:embeddings_count] || 'N/A'}"
|
29
|
+
puts "Embeddings Ready: #{status[:embeddings_ready] || 'N/A'}"
|
30
|
+
puts "Message: #{status[:message] || 'No message available'}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ragdoll
|
4
|
+
module CLI
|
5
|
+
class Update
|
6
|
+
def call(id, options)
|
7
|
+
client = StandaloneClient.new
|
8
|
+
|
9
|
+
puts "Updating document ID: #{id}"
|
10
|
+
puts "Options: #{options.to_h}" unless options.to_h.empty?
|
11
|
+
puts
|
12
|
+
|
13
|
+
update_options = {}
|
14
|
+
update_options[:title] = options[:title] if options[:title]
|
15
|
+
|
16
|
+
if update_options.empty?
|
17
|
+
puts 'No updates provided. Use --title to update the document title.'
|
18
|
+
return
|
19
|
+
end
|
20
|
+
|
21
|
+
result = client.update_document(id: id, **update_options)
|
22
|
+
|
23
|
+
if result[:success]
|
24
|
+
puts "Document ID #{id} updated successfully."
|
25
|
+
puts result[:message] if result[:message]
|
26
|
+
else
|
27
|
+
puts "Failed to update document ID #{id}."
|
28
|
+
puts result[:message] if result[:message]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
module Ragdoll
|
7
|
+
module CLI
|
8
|
+
class ConfigurationLoader
|
9
|
+
DEFAULT_CONFIG_PATH = File.expand_path('~/.ragdoll/config.yml')
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@config_path = ENV['RAGDOLL_CONFIG'] || DEFAULT_CONFIG_PATH
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
def load
|
17
|
+
config = load_config_file
|
18
|
+
configure_ragdoll(config)
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
def create_default_config
|
23
|
+
ensure_config_directory
|
24
|
+
|
25
|
+
default_config = {
|
26
|
+
'llm_provider' => 'openai',
|
27
|
+
'embedding_model' => 'text-embedding-3-small',
|
28
|
+
'chunk_size' => 1000,
|
29
|
+
'chunk_overlap' => 200,
|
30
|
+
'search_similarity_threshold' => 0.7,
|
31
|
+
'max_search_results' => 10,
|
32
|
+
'database_config' => {
|
33
|
+
'adapter' => 'postgresql',
|
34
|
+
'database' => 'ragdoll_development',
|
35
|
+
'host' => 'localhost',
|
36
|
+
'port' => 5432,
|
37
|
+
'username' => ENV['USER'] || 'postgres',
|
38
|
+
'auto_migrate' => true
|
39
|
+
},
|
40
|
+
'log_level' => 'warn',
|
41
|
+
'log_file' => File.expand_path('~/.ragdoll/ragdoll.log')
|
42
|
+
}
|
43
|
+
|
44
|
+
File.write(@config_path, YAML.dump(default_config))
|
45
|
+
default_config
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
def config_exists?
|
50
|
+
File.exist?(@config_path)
|
51
|
+
end
|
52
|
+
|
53
|
+
attr_reader :config_path
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def load_config_file
|
58
|
+
return create_default_config unless config_exists?
|
59
|
+
|
60
|
+
YAML.load_file(@config_path)
|
61
|
+
rescue StandardError => e
|
62
|
+
puts "Warning: Could not load config file #{@config_path}: #{e.message}"
|
63
|
+
puts 'Using default configuration.'
|
64
|
+
create_default_config
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
def configure_ragdoll(config)
|
69
|
+
Ragdoll::Core.configure do |ragdoll_config|
|
70
|
+
# LLM and embedding configuration
|
71
|
+
if ragdoll_config.respond_to?(:llm_provider=)
|
72
|
+
ragdoll_config.llm_provider = config['llm_provider']&.to_sym || :openai
|
73
|
+
end
|
74
|
+
if ragdoll_config.respond_to?(:embedding_model=)
|
75
|
+
ragdoll_config.embedding_model = config['embedding_model'] || 'text-embedding-3-small'
|
76
|
+
end
|
77
|
+
|
78
|
+
# Processing settings
|
79
|
+
if ragdoll_config.respond_to?(:chunk_size=)
|
80
|
+
ragdoll_config.chunk_size = config['chunk_size'] || 1000
|
81
|
+
end
|
82
|
+
if ragdoll_config.respond_to?(:chunk_overlap=)
|
83
|
+
ragdoll_config.chunk_overlap = config['chunk_overlap'] || 200
|
84
|
+
end
|
85
|
+
if ragdoll_config.respond_to?(:search_similarity_threshold=)
|
86
|
+
ragdoll_config.search_similarity_threshold = config['search_similarity_threshold'] || 0.7
|
87
|
+
end
|
88
|
+
if ragdoll_config.respond_to?(:max_search_results=)
|
89
|
+
ragdoll_config.max_search_results = config['max_search_results'] || 10
|
90
|
+
end
|
91
|
+
|
92
|
+
# Database configuration - avoid direct setting if method doesn't exist
|
93
|
+
db_config = config['database_config'] || {
|
94
|
+
'adapter' => 'postgresql',
|
95
|
+
'database' => 'ragdoll_development',
|
96
|
+
'host' => 'localhost',
|
97
|
+
'port' => 5432,
|
98
|
+
'username' => ENV['USER'] || 'postgres',
|
99
|
+
'auto_migrate' => true
|
100
|
+
}
|
101
|
+
# Set database configuration only if the method exists
|
102
|
+
ragdoll_config.database_config = db_config if ragdoll_config.respond_to?(:database_config=)
|
103
|
+
|
104
|
+
# Logging configuration
|
105
|
+
if ragdoll_config.respond_to?(:log_level=)
|
106
|
+
ragdoll_config.log_level = config['log_level']&.to_sym || :warn
|
107
|
+
end
|
108
|
+
if ragdoll_config.respond_to?(:log_file=)
|
109
|
+
ragdoll_config.log_file = config['log_file'] || File.expand_path('~/.ragdoll/ragdoll.log')
|
110
|
+
end
|
111
|
+
|
112
|
+
# Set API keys from environment variables or config
|
113
|
+
if ragdoll_config.respond_to?(:openai_api_key=)
|
114
|
+
ragdoll_config.openai_api_key = ENV['OPENAI_API_KEY'] || config.dig('api_keys', 'openai')
|
115
|
+
end
|
116
|
+
if ragdoll_config.respond_to?(:anthropic_api_key=)
|
117
|
+
ragdoll_config.anthropic_api_key = ENV['ANTHROPIC_API_KEY'] || config.dig('api_keys',
|
118
|
+
'anthropic')
|
119
|
+
end
|
120
|
+
if ragdoll_config.respond_to?(:google_api_key=)
|
121
|
+
ragdoll_config.google_api_key = ENV['GOOGLE_API_KEY'] || config.dig('api_keys', 'google')
|
122
|
+
end
|
123
|
+
if ragdoll_config.respond_to?(:azure_api_key=)
|
124
|
+
ragdoll_config.azure_api_key = ENV['AZURE_OPENAI_API_KEY'] || config.dig('api_keys', 'azure')
|
125
|
+
end
|
126
|
+
if ragdoll_config.respond_to?(:huggingface_api_key=)
|
127
|
+
ragdoll_config.huggingface_api_key = ENV['HUGGINGFACE_API_KEY'] || config.dig('api_keys',
|
128
|
+
'huggingface')
|
129
|
+
end
|
130
|
+
|
131
|
+
if config.dig('api_keys', 'ollama_url') && ragdoll_config.respond_to?(:ollama_url=)
|
132
|
+
ragdoll_config.ollama_url = config.dig('api_keys', 'ollama_url')
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
def ensure_config_directory
|
139
|
+
config_dir = File.dirname(@config_path)
|
140
|
+
FileUtils.mkdir_p(config_dir) unless Dir.exist?(config_dir)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ragdoll
|
4
|
+
module CLI
|
5
|
+
class StandaloneClient
|
6
|
+
include DebugMe
|
7
|
+
def add_document(path, **options)
|
8
|
+
Ragdoll.add_document(path: path, **options)
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
def document_status(id)
|
13
|
+
Ragdoll.document_status(id: id)
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
def get_document(id)
|
18
|
+
Ragdoll.get_document(id: id)
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
def update_document(id, **options)
|
23
|
+
Ragdoll.update_document(id: id, **options)
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
def delete_document(id)
|
28
|
+
Ragdoll.delete_document(id: id)
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
def list_documents(**options)
|
33
|
+
Ragdoll.list_documents(**options)
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
def search(query, **options)
|
38
|
+
Ragdoll.search(query: query, **options)
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
def get_context(query, **options)
|
43
|
+
Ragdoll.get_context(query: query, **options)
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
def enhance_prompt(prompt, **options)
|
48
|
+
Ragdoll.enhance_prompt(prompt: prompt, **options)
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
def stats
|
53
|
+
Ragdoll.stats
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
def healthy?
|
58
|
+
Ragdoll.healthy?
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
def configuration
|
63
|
+
Ragdoll.configuration
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|