llm_chain 0.5.1 → 0.5.3

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: 6d2f08734c93afa3880316d14f129a90502e0f6d9094d939257a5bf0740b6754
4
- data.tar.gz: a1f6665f3dd39c1401e54770e8fd23f10fba1b47195f88b461b2e76fe4a0212a
3
+ metadata.gz: 8c94520a98ace3d2bb61ca2b470af041e0f95d6818120ce01dfc5a9cfe76316b
4
+ data.tar.gz: 5155099cdf777ecaed3a30c9da1e7e200476258369ef3b976967888daf001876
5
5
  SHA512:
6
- metadata.gz: aebdbe64169f31b55ea55278103769acd71c4a8d786c1e84235abd9d2e6f271dcfe9eeba46796675c096a4bef3a34843a5f093dddf5964ad0fdfe974d18b2d79
7
- data.tar.gz: 57f61024965d99528e8e0f56c60106af3168a408bc0f612b4c1fbca7ac79eeb46b564bee50f648128e34850268717f57362f96911b4be290a8a4288bcc548d83
6
+ metadata.gz: b37c6ed16c6b6a66d1f9c6e2a62717e576c5211aba605b98b97e5ba54b436d9a38602aabcedf34a23963ee034d6332dadefe03fa6c6a5d4d3f4941b2df9efd88
7
+ data.tar.gz: 4e5c3b6921e4f0656ea8266ca67a00dbcbc8c11736573df9172b8cb2d8821d3799f87085f31e7975d916d56c29f10a4637c6df5f102520fc2da3f5284143ef79
data/CHANGELOG.md CHANGED
@@ -7,6 +7,43 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.5.3] - 2025-07-05
11
+
12
+ ### Added
13
+ * **CLI Executable** (`llm-chain`) with commands:
14
+ * `chat` – one-off prompt
15
+ * `diagnose` – system diagnostics
16
+ * `tools list` – list default tools
17
+ * `repl` – interactive Read-Eval-Print Loop with in-memory history and helper slash-commands
18
+
19
+ ### Changed
20
+ * CLI autodetects Bundler only in development repo to avoid gem conflicts.
21
+
22
+ ### Fixed
23
+ * Version conflicts when running CLI inside unrelated Bundler projects.
24
+
25
+ ## [0.5.2] - 2025-01-XX
26
+
27
+ ### Added
28
+ - **Configuration Validator** - Comprehensive system validation before chain initialization
29
+ - **System Diagnostics** - `LLMChain.diagnose_system` method for health checks
30
+ - **Retry Logic** - Exponential backoff for HTTP requests with configurable max retries
31
+ - **Enhanced Logging** - Structured logging with debug mode support
32
+ - **Internet Connectivity Detection** - Automatic offline mode detection
33
+ - **Code Extraction Improvements** - Better parsing of code blocks and inline commands
34
+
35
+ ### Changed
36
+ - **Improved Error Handling** - Better error messages with suggested solutions
37
+ - **Enhanced WebSearch** - More robust fallback mechanisms and timeout handling
38
+ - **CodeInterpreter Enhancements** - Improved code extraction from various formats
39
+ - **Better Validation** - Early detection of configuration issues with helpful warnings
40
+
41
+ ### Fixed
42
+ - **WebSearch Stability** - Fixed timeout and connection issues with retry logic
43
+ - **Code Block Parsing** - Resolved issues with multiline regex and Windows line endings
44
+ - **Graceful Degradation** - Better handling of offline scenarios and API failures
45
+ - **Memory Leaks** - Improved cleanup of temporary files and resources
46
+
10
47
  ## [0.5.1] - 2025-06-26
11
48
 
12
49
  ### Added
@@ -46,6 +83,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
46
83
  ### Changed
47
84
  - Initial stable release with core functionality
48
85
 
49
- [Unreleased]: https://github.com/FuryCow/llm_chain/compare/v0.5.1...HEAD
86
+ [Unreleased]: https://github.com/FuryCow/llm_chain/compare/v0.5.3...HEAD
87
+ [0.5.3]: https://github.com/FuryCow/llm_chain/compare/v0.5.2...v0.5.3
88
+ [0.5.2]: https://github.com/FuryCow/llm_chain/compare/v0.5.1...v0.5.2
50
89
  [0.5.1]: https://github.com/FuryCow/llm_chain/compare/v0.5.0...v0.5.1
51
90
  [0.5.0]: https://github.com/FuryCow/llm_chain/releases/tag/v0.5.0
data/README.md CHANGED
@@ -8,14 +8,16 @@
8
8
 
9
9
  LLMChain is a Ruby analog of LangChain, providing a unified interface for interacting with various LLMs, built-in tool system, and RAG (Retrieval-Augmented Generation) support.
10
10
 
11
- ## 🎉 What's New in v0.5.1
11
+ ## 🎉 What's New in v0.5.3
12
12
 
13
- - **Google Search Integration** - Accurate, up-to-date search results
14
- - **Fixed Calculator** - Improved expression parsing and evaluation
15
- - **Enhanced Code Interpreter** - Better code extraction from prompts
16
- - **Production-Ready Output** - Clean interface without debug noise
17
- - **Quick Chain Creation** - Simple `LLMChain.quick_chain` method
18
- - **Simplified Configuration** - Easy setup with sensible defaults
13
+ * 🖥️ **New CLI executable** `llm-chain`
14
+ * `chat` ask a one-off question from your shell
15
+ * `repl` interactive session with conversation memory and helper commands (`/help`, `/mem clear`, `/tools list`)
16
+ * `diagnose` run the built-in environment health-check
17
+ * `tools list` inspect available tools
18
+ * 🔄 **Bundler-aware loading** CLI detects if it’s executed inside the gem repo and avoids version clashes with external Gemfiles.
19
+
20
+ That’s all you need to start talking to LLMs straight from the terminal. See the **Command-line Interface** section below for usage examples.
19
21
 
20
22
  ## ✨ Key Features
21
23
 
@@ -80,6 +82,87 @@ response = chain.ask("Hello! How are you?")
80
82
  puts response
81
83
  ```
82
84
 
85
+ ## 🖥️ Command-line Interface (v0.5.3+)
86
+
87
+ Alongside the Ruby API, LLMChain ships with a convenient CLI executable `llm-chain`.
88
+
89
+ ### Basic commands
90
+
91
+ ```bash
92
+ # One-off question
93
+ llm-chain chat "Hello! How are you?"
94
+
95
+ # Interactive REPL with conversation memory (/help in session)
96
+ llm-chain repl
97
+
98
+ # System diagnostics (same as LLMChain.diagnose_system)
99
+ llm-chain diagnose
100
+
101
+ # List default tools
102
+ llm-chain tools list
103
+
104
+ # Show gem version
105
+ llm-chain -v
106
+ ```
107
+
108
+ The CLI is installed automatically with the gem. If your shell doesn’t find the command, make sure RubyGems’ bindir is in your `$PATH` or use Bundler-aware launch:
109
+
110
+ ```bash
111
+ bundle exec llm-chain chat "…"
112
+ ```
113
+
114
+ Set `LLM_CHAIN_DEBUG=true` to print extra logs.
115
+
116
+ ## 🔍 System Diagnostics (v0.5.2+)
117
+
118
+ Before diving into development, it's recommended to check your system configuration:
119
+
120
+ ```ruby
121
+ require 'llm_chain'
122
+
123
+ # Run comprehensive system diagnostics
124
+ LLMChain.diagnose_system
125
+ # 🔍 LLMChain System Diagnostics
126
+ # ==================================================
127
+ # 📋 System Components:
128
+ # Ruby: ✅ (3.2.2)
129
+ # Python: ✅
130
+ # Node.js: ✅
131
+ # Internet: ✅
132
+ # Ollama: ✅
133
+ # 🔑 API Keys:
134
+ # Openai: ❌
135
+ # Google_search: ❌
136
+ # 💡 Recommendations:
137
+ # • Configure API keys for enhanced features
138
+ # • Start Ollama server: ollama serve
139
+ ```
140
+
141
+ ### Configuration Validation
142
+
143
+ Chains now validate their configuration on startup:
144
+
145
+ ```ruby
146
+ # Automatic validation (v0.5.2+)
147
+ begin
148
+ chain = LLMChain.quick_chain(model: "qwen3:1.7b")
149
+ rescue LLMChain::Error => e
150
+ puts "Configuration issue: #{e.message}"
151
+ end
152
+
153
+ # Disable validation if needed
154
+ chain = LLMChain.quick_chain(
155
+ model: "qwen3:1.7b",
156
+ validate_config: false
157
+ )
158
+
159
+ # Manual validation
160
+ LLMChain::ConfigurationValidator.validate_chain_config!(
161
+ model: "qwen3:1.7b",
162
+ tools: LLMChain::Tools::ToolManager.create_default_toolset
163
+ )
164
+ ```
165
+
83
166
  ## 🛠️ Tool System
84
167
 
85
168
  ### Automatic Tool Usage
@@ -130,9 +213,11 @@ results = search.call("Which is the latest version of Ruby?")
130
213
  # Works even without Google API configured
131
214
  ```
132
215
 
133
- #### 💻 Code Interpreter
216
+ #### 💻 Code Interpreter (Enhanced in v0.5.2)
134
217
  ```ruby
135
218
  interpreter = LLMChain::Tools::CodeInterpreter.new
219
+
220
+ # Standard markdown blocks
136
221
  result = interpreter.call(<<~CODE)
137
222
  ```ruby
138
223
  def factorial(n)
@@ -141,10 +226,25 @@ result = interpreter.call(<<~CODE)
141
226
  puts factorial(5)
142
227
  ```
143
228
  CODE
229
+
230
+ # Inline code commands (v0.5.2+)
231
+ result = interpreter.call("Execute code: puts 'Hello World!'")
232
+
233
+ # Code without language specification
234
+ result = interpreter.call(<<~CODE)
235
+ ```
236
+ numbers = [1, 2, 3, 4, 5]
237
+ puts numbers.sum
238
+ ```
239
+ CODE
240
+
241
+ # Windows line endings support (v0.5.2+)
242
+ result = interpreter.call("```ruby\r\nputs 'Windows compatible'\r\n```")
243
+
144
244
  puts result[:formatted]
145
245
  ```
146
246
 
147
- ## ⚙️ Configuration (v0.5.1+)
247
+ ## ⚙️ Configuration (v0.5.2+)
148
248
 
149
249
  ```ruby
150
250
  # Global configuration
@@ -158,14 +258,48 @@ end
158
258
  # Quick chain with default settings
159
259
  chain = LLMChain.quick_chain
160
260
 
161
- # Override settings per chain
261
+ # Override settings per chain (v0.5.2+)
162
262
  chain = LLMChain.quick_chain(
163
263
  model: "gpt-4",
164
264
  tools: false, # Disable tools
165
- memory: false # Disable memory
265
+ memory: false, # Disable memory
266
+ validate_config: false # Skip validation
166
267
  )
167
268
  ```
168
269
 
270
+ ### Debug Mode (v0.5.2+)
271
+
272
+ Enable detailed logging for troubleshooting:
273
+
274
+ ```bash
275
+ # Enable debug logging
276
+ export LLM_CHAIN_DEBUG=true
277
+
278
+ # Or in Ruby
279
+ ENV['LLM_CHAIN_DEBUG'] = 'true'
280
+ ```
281
+
282
+ ### Validation and Error Handling (v0.5.2+)
283
+
284
+ ```ruby
285
+ # Comprehensive environment check
286
+ results = LLMChain::ConfigurationValidator.validate_environment
287
+ puts "Ollama available: #{results[:ollama]}"
288
+ puts "Internet: #{results[:internet]}"
289
+ puts "Warnings: #{results[:warnings]}"
290
+
291
+ # Chain validation with custom settings
292
+ begin
293
+ LLMChain::ConfigurationValidator.validate_chain_config!(
294
+ model: "gpt-4",
295
+ tools: [LLMChain::Tools::Calculator.new, LLMChain::Tools::WebSearch.new]
296
+ )
297
+ rescue LLMChain::ConfigurationValidator::ValidationError => e
298
+ puts "Setup issue: #{e.message}"
299
+ # Handle configuration problems
300
+ end
301
+ ```
302
+
169
303
  ### Creating Custom Tools
170
304
 
171
305
  ```ruby
@@ -424,23 +558,64 @@ openai = LLMChain::Clients::OpenAI.new(
424
558
  )
425
559
  ```
426
560
 
427
- ## 🔧 Error Handling
561
+ ## 🔧 Error Handling (Enhanced in v0.5.2)
428
562
 
429
563
  ```ruby
430
564
  begin
431
565
  chain = LLMChain::Chain.new(model: "qwen3:1.7b")
432
566
  response = chain.ask("Complex query")
567
+ rescue LLMChain::ConfigurationValidator::ValidationError => e
568
+ puts "Configuration issue: #{e.message}"
569
+ # Use LLMChain.diagnose_system to check setup
433
570
  rescue LLMChain::UnknownModelError => e
434
571
  puts "Unknown model: #{e.message}"
572
+ # Check available models with ollama list
435
573
  rescue LLMChain::ClientError => e
436
574
  puts "Client error: #{e.message}"
575
+ # Network or API issues
437
576
  rescue LLMChain::TimeoutError => e
438
577
  puts "Timeout exceeded: #{e.message}"
578
+ # Increase timeout or use faster model
439
579
  rescue LLMChain::Error => e
440
580
  puts "General LLMChain error: #{e.message}"
441
581
  end
442
582
  ```
443
583
 
584
+ ### Automatic Retry Logic (v0.5.2+)
585
+
586
+ WebSearch and other tools now include automatic retry with exponential backoff:
587
+
588
+ ```ruby
589
+ # Retry configuration is automatic, but you can observe it:
590
+ ENV['LLM_CHAIN_DEBUG'] = 'true'
591
+
592
+ search = LLMChain::Tools::WebSearch.new
593
+ result = search.call("search query")
594
+ # [WebSearch] Retrying search (1/3) after 0.5s: Net::TimeoutError
595
+ # [WebSearch] Retrying search (2/3) after 1.0s: Net::TimeoutError
596
+ # [WebSearch] Search failed after 3 attempts: Net::TimeoutError
597
+
598
+ # Tools gracefully degrade to fallback methods when possible
599
+ puts result[:formatted] # Still provides useful response
600
+ ```
601
+
602
+ ### Graceful Degradation
603
+
604
+ ```ruby
605
+ # Tools handle failures gracefully
606
+ calculator = LLMChain::Tools::Calculator.new
607
+ web_search = LLMChain::Tools::WebSearch.new
608
+ code_runner = LLMChain::Tools::CodeInterpreter.new
609
+
610
+ # Even with network issues, you get useful responses:
611
+ search_result = web_search.call("latest Ruby version")
612
+ # Falls back to hardcoded data for common queries
613
+
614
+ # Safe code execution with timeout protection:
615
+ code_result = code_runner.call("puts 'Hello World!'")
616
+ # Executes safely with proper sandboxing
617
+ ```
618
+
444
619
  ## 📚 Usage Examples
445
620
 
446
621
  ### Chatbot with Tools
@@ -551,11 +726,17 @@ chain.ask(prompt, stream: false, rag_context: false, rag_options: {})
551
726
 
552
727
  ## 🛣️ Roadmap
553
728
 
554
- ### v0.6.0
729
+ ### v0.5.2 ✅ Completed
730
+ - [x] System diagnostics and health checks
731
+ - [x] Configuration validation
732
+ - [x] Enhanced error handling with retry logic
733
+ - [x] Improved code extraction and tool stability
734
+
735
+ ### v0.6.0 (Next)
555
736
  - [ ] ReAct agents and multi-step reasoning
556
737
  - [ ] More tools (file system, database queries)
557
738
  - [ ] Claude integration
558
- - [ ] Enhanced error handling
739
+ - [ ] Advanced logging and metrics
559
740
 
560
741
  ### v0.7.0
561
742
  - [ ] Multi-agent systems
data/exe/llm-chain ADDED
@@ -0,0 +1,126 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Load Bundler only if running from the development repo (Gemfile present)
5
+ if File.exist?(File.expand_path("../../Gemfile", __dir__))
6
+ begin
7
+ require "bundler/setup"
8
+ rescue LoadError
9
+ warn "[llm-chain] Bundler not available; continuing without it"
10
+ end
11
+ end
12
+
13
+ require "llm_chain"
14
+ require "optparse"
15
+ require "readline"
16
+
17
+ USAGE = <<~TEXT.freeze
18
+ Usage: llm-chain <command> [options]
19
+
20
+ Commands:
21
+ chat <prompt> Send prompt to quick_chain and print response
22
+ repl Start interactive REPL session
23
+ diagnose Run system diagnostics
24
+ tools list List registered tools in the default toolset
25
+ version Print LLMChain gem version
26
+
27
+ Environment variables:
28
+ LLM_CHAIN_DEBUG Enable verbose diagnostic logs
29
+ TEXT
30
+
31
+ # Exit with usage if no command
32
+ if ARGV.empty?
33
+ warn USAGE
34
+ exit 1
35
+ end
36
+
37
+ command = ARGV.shift
38
+
39
+ case command
40
+ when "repl"
41
+ puts "LLMChain REPL — type /help for commands, /exit to quit"
42
+ chain = LLMChain.quick_chain
43
+
44
+ loop do
45
+ line = Readline.readline("> ", true)
46
+ break if line.nil? || line.strip == "/exit" || line.strip == "/quit"
47
+
48
+ case line.strip
49
+ when "/help"
50
+ puts "/exit Exit REPL\n" \
51
+ "/mem clear Clear conversation memory\n" \
52
+ "/tools list List available tools"
53
+ next
54
+ when "/mem clear"
55
+ chain.memory.clear if chain.memory.respond_to?(:clear)
56
+ puts "[memory cleared]"
57
+ next
58
+ when "/tools list"
59
+ if chain.tools.respond_to?(:tools_description)
60
+ puts chain.tools.tools_description
61
+ else
62
+ puts "No ToolManager attached"
63
+ end
64
+ next
65
+ end
66
+
67
+ # Empty input => skip
68
+ next if line.strip.empty?
69
+
70
+ begin
71
+ response = chain.ask(line)
72
+ puts response
73
+ rescue => e
74
+ warn "Error: #{e.message}"
75
+ end
76
+ end
77
+
78
+ puts "Bye!"
79
+
80
+ when "chat"
81
+ # Collect prompt from remaining args or STDIN
82
+ prompt = if ARGV.empty?
83
+ puts "Enter prompt (end with CTRL+D):"
84
+ STDIN.read
85
+ else
86
+ ARGV.join(" ")
87
+ end
88
+ if prompt.nil? || prompt.strip.empty?
89
+ warn "No prompt provided"
90
+ exit 1
91
+ end
92
+
93
+ begin
94
+ chain = LLMChain.quick_chain
95
+ response = chain.ask(prompt)
96
+ puts "\n=== Response ===\n"
97
+ puts response
98
+ rescue Interrupt
99
+ warn "Interrupted"
100
+ rescue => e
101
+ warn "Error: #{e.message}"
102
+ exit 1
103
+ end
104
+
105
+ when "diagnose"
106
+ LLMChain.diagnose_system
107
+
108
+ when "tools"
109
+ sub = ARGV.shift
110
+ case sub
111
+ when "list"
112
+ tm = LLMChain::Tools::ToolManager.create_default_toolset
113
+ puts tm.tools_description
114
+ else
115
+ warn "Unknown tools subcommand"; warn USAGE
116
+ exit 1
117
+ end
118
+
119
+ when "version", "--version", "-v"
120
+ puts LlmChain::VERSION
121
+
122
+ else
123
+ warn "Unknown command: #{command}"
124
+ warn USAGE
125
+ exit 1
126
+ end
@@ -9,7 +9,22 @@ module LLMChain
9
9
  # @param tools [Array<Tool>] Массив инструментов
10
10
  # @param retriever [#search] RAG-ретривер (Weaviate, Pinecone и т.д.)
11
11
  # @param client_options [Hash] Опции для клиента LLM
12
- def initialize(model: nil, memory: nil, tools: [], retriever: nil, **client_options)
12
+ def initialize(model: nil, memory: nil, tools: [], retriever: nil, validate_config: true, **client_options)
13
+ # Валидация конфигурации (можно отключить через validate_config: false)
14
+ if validate_config
15
+ begin
16
+ ConfigurationValidator.validate_chain_config!(
17
+ model: model,
18
+ tools: tools,
19
+ memory: memory,
20
+ retriever: retriever,
21
+ **client_options
22
+ )
23
+ rescue ConfigurationValidator::ValidationError => e
24
+ raise Error, "Configuration validation failed: #{e.message}"
25
+ end
26
+ end
27
+
13
28
  @model = model
14
29
  @memory = memory || Memory::Array.new
15
30
  @tools = tools