Class: Ragnar::Config
- Inherits:
-
Object
- Object
- Ragnar::Config
- Includes:
- Singleton
- Defined in:
- lib/ragnar/config.rb
Constant Summary collapse
- CONFIG_FILENAMES =
['.ragnar.yml', '.ragnarrc.yml', 'ragnar.yml'].freeze
Instance Method Summary collapse
- #available_profiles ⇒ Object
- #chunk_overlap ⇒ Object
- #chunk_size ⇒ Object
- #config_exists? ⇒ Boolean
-
#config_file_path ⇒ Object
Config file management.
-
#create_chat ⇒ Object
Create a new RubyLLM chat instance with the active profile’s settings.
-
#database_path ⇒ Object
Common config accessors.
- #embedding_model ⇒ Object
- #enable_query_rewriting? ⇒ Boolean
- #enable_reranking? ⇒ Boolean
-
#generate_config_file(path = nil) ⇒ Object
Generate a config file with current/default settings.
-
#get(key_path, default = nil) ⇒ Object
Main config access method.
- #history_file ⇒ Object
-
#initialize ⇒ Config
constructor
A new instance of Config.
- #interactive_prompt ⇒ Object
- #llm_api_key ⇒ Object
- #llm_gguf_file ⇒ Object
- #llm_model ⇒ Object
- #llm_profile ⇒ Object
- #llm_profile_name ⇒ Object
- #llm_profiles ⇒ Object
- #llm_provider ⇒ Object
- #models_dir ⇒ Object
- #query_top_k ⇒ Object
- #quiet_mode? ⇒ Boolean
- #reload! ⇒ Object
- #reranker_model ⇒ Object
-
#set_active_profile(name) ⇒ Object
LLM Profile support Profiles allow switching between LLM providers/models via –profile flag Backwards compatible: flat llm.provider/llm.default_model still work if no profiles defined.
- #show_progress? ⇒ Boolean
Constructor Details
#initialize ⇒ Config
Returns a new instance of Config.
14 15 16 17 |
# File 'lib/ragnar/config.rb', line 14 def initialize @config = load_config ensure_directories_exist end |
Instance Method Details
#available_profiles ⇒ Object
97 98 99 |
# File 'lib/ragnar/config.rb', line 97 def available_profiles llm_profiles.keys end |
#chunk_overlap ⇒ Object
56 57 58 |
# File 'lib/ragnar/config.rb', line 56 def chunk_overlap get('embeddings.chunk_overlap', Ragnar::DEFAULT_CHUNK_OVERLAP) end |
#chunk_size ⇒ Object
52 53 54 |
# File 'lib/ragnar/config.rb', line 52 def chunk_size get('embeddings.chunk_size', Ragnar::DEFAULT_CHUNK_SIZE) end |
#config_exists? ⇒ Boolean
163 164 165 |
# File 'lib/ragnar/config.rb', line 163 def config_exists? !@config_file_path.nil? end |
#config_file_path ⇒ Object
Config file management
159 160 161 |
# File 'lib/ragnar/config.rb', line 159 def config_file_path @config_file_path end |
#create_chat ⇒ Object
Create a new RubyLLM chat instance with the active profile’s settings
102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/ragnar/config.rb', line 102 def create_chat api_key = llm_api_key provider = llm_provider.to_sym # Configure RubyLLM with the API key if present if api_key configure_provider_api_key(provider, api_key) end RubyLLM.chat(provider: provider, model: llm_model) end |
#database_path ⇒ Object
Common config accessors
36 37 38 |
# File 'lib/ragnar/config.rb', line 36 def database_path get('storage.database_path', default_database_path) end |
#embedding_model ⇒ Object
48 49 50 |
# File 'lib/ragnar/config.rb', line 48 def get('embeddings.model', Ragnar::DEFAULT_EMBEDDING_MODEL) end |
#enable_query_rewriting? ⇒ Boolean
146 147 148 |
# File 'lib/ragnar/config.rb', line 146 def enable_query_rewriting? get('query.enable_query_rewriting', true) end |
#enable_reranking? ⇒ Boolean
150 151 152 |
# File 'lib/ragnar/config.rb', line 150 def enable_reranking? get('query.enable_reranking', true) end |
#generate_config_file(path = nil) ⇒ Object
Generate a config file with current/default settings
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 |
# File 'lib/ragnar/config.rb', line 173 def generate_config_file(path = nil) path ||= File.('~/.ragnar.yml') config_content = { 'storage' => { 'database_path' => '~/.cache/ragnar/database', 'models_dir' => '~/.cache/ragnar/models', 'history_file' => '~/.cache/ragnar/history' }, 'embeddings' => { 'model' => Ragnar::DEFAULT_EMBEDDING_MODEL, 'chunk_size' => Ragnar::DEFAULT_CHUNK_SIZE, 'chunk_overlap' => Ragnar::DEFAULT_CHUNK_OVERLAP }, 'umap' => { 'reduced_dimensions' => Ragnar::DEFAULT_REDUCED_DIMENSIONS, 'n_neighbors' => 15, 'min_dist' => 0.1, 'model_filename' => 'umap_model.bin' }, 'llm' => { 'default_profile' => 'red_candle', 'profiles' => { 'red_candle' => { 'provider' => 'red_candle', 'model' => 'MaziyarPanahi/Qwen3-4B-GGUF' }, 'opus' => { 'provider' => 'anthropic', 'model' => 'claude-opus-4-6' }, 'sonnet' => { 'provider' => 'anthropic', 'model' => 'claude-sonnet-4-6' } } }, 'query' => { 'top_k' => 3, 'enable_query_rewriting' => true, 'enable_reranking' => true, 'reranker_model' => 'BAAI/bge-reranker-base' }, 'interactive' => { 'prompt' => 'ragnar> ', 'quiet_mode' => true }, 'output' => { 'show_progress' => true } } # Ensure parent directory exists FileUtils.mkdir_p(File.dirname(path)) # Write config file with comments File.write(path, generate_yaml_with_comments(config_content)) path end |
#get(key_path, default = nil) ⇒ Object
Main config access method
20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/ragnar/config.rb', line 20 def get(key_path, default = nil) keys = key_path.split('.') value = keys.reduce(@config) { |config, key| config&.dig(key) } # Use default only if value is nil (not false) result = value.nil? ? default : value # Expand paths that start with ~ if result.is_a?(String) && result.start_with?('~') File.(result) else result end end |
#history_file ⇒ Object
40 41 42 |
# File 'lib/ragnar/config.rb', line 40 def history_file get('storage.history_file', default_history_file) end |
#interactive_prompt ⇒ Object
130 131 132 |
# File 'lib/ragnar/config.rb', line 130 def interactive_prompt get('interactive.prompt', "ragnar> ") end |
#llm_api_key ⇒ Object
126 127 128 |
# File 'lib/ragnar/config.rb', line 126 def llm_api_key llm_profile&.dig('api_key') || get('llm.api_key', nil) end |
#llm_gguf_file ⇒ Object
122 123 124 |
# File 'lib/ragnar/config.rb', line 122 def llm_gguf_file get('llm.default_gguf_file', "Qwen3-4B.Q4_K_M.gguf") end |
#llm_model ⇒ Object
118 119 120 |
# File 'lib/ragnar/config.rb', line 118 def llm_model llm_profile&.dig('model') || get('llm.default_model', 'MaziyarPanahi/Qwen3-4B-GGUF') end |
#llm_profile ⇒ Object
93 94 95 |
# File 'lib/ragnar/config.rb', line 93 def llm_profile llm_profiles[llm_profile_name] || llm_profiles.values.first end |
#llm_profile_name ⇒ Object
74 75 76 |
# File 'lib/ragnar/config.rb', line 74 def llm_profile_name @active_profile || get('llm.default_profile', nil) || llm_profiles.keys.first || 'default' end |
#llm_profiles ⇒ Object
78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/ragnar/config.rb', line 78 def llm_profiles configured = get('llm.profiles', nil) if configured.is_a?(Hash) && !configured.empty? configured else # Backwards compat: synthesize a profile from flat keys { 'default' => { 'provider' => get('llm.provider', 'red_candle'), 'model' => get('llm.default_model', 'MaziyarPanahi/Qwen3-4B-GGUF') } } end end |
#llm_provider ⇒ Object
114 115 116 |
# File 'lib/ragnar/config.rb', line 114 def llm_provider llm_profile&.dig('provider') || get('llm.provider', 'red_candle') end |
#models_dir ⇒ Object
44 45 46 |
# File 'lib/ragnar/config.rb', line 44 def models_dir get('storage.models_dir', default_models_dir) end |
#query_top_k ⇒ Object
142 143 144 |
# File 'lib/ragnar/config.rb', line 142 def query_top_k get('query.top_k', 3) end |
#quiet_mode? ⇒ Boolean
134 135 136 |
# File 'lib/ragnar/config.rb', line 134 def quiet_mode? get('interactive.quiet_mode', true) end |
#reload! ⇒ Object
167 168 169 170 |
# File 'lib/ragnar/config.rb', line 167 def reload! @config = load_config ensure_directories_exist end |
#reranker_model ⇒ Object
154 155 156 |
# File 'lib/ragnar/config.rb', line 154 def reranker_model get('query.reranker_model', 'BAAI/bge-reranker-base') end |
#set_active_profile(name) ⇒ Object
LLM Profile support Profiles allow switching between LLM providers/models via –profile flag Backwards compatible: flat llm.provider/llm.default_model still work if no profiles defined
64 65 66 67 68 69 70 71 72 |
# File 'lib/ragnar/config.rb', line 64 def set_active_profile(name) name = name.to_s profiles = llm_profiles unless profiles.key?(name) available = profiles.keys.join(', ') raise ArgumentError, "Unknown profile '#{name}'. Available profiles: #{available}" end @active_profile = name end |
#show_progress? ⇒ Boolean
138 139 140 |
# File 'lib/ragnar/config.rb', line 138 def show_progress? get('output.show_progress', true) end |