llm_chain 0.5.3 → 0.5.5

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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -2
  3. data/README.md +15 -6
  4. data/examples/quick_demo.rb +1 -1
  5. data/examples/tools_example.rb +2 -2
  6. data/exe/llm-chain +7 -4
  7. data/lib/llm_chain/builders/memory_context.rb +24 -0
  8. data/lib/llm_chain/builders/prompt.rb +26 -0
  9. data/lib/llm_chain/builders/rag_documents.rb +25 -0
  10. data/lib/llm_chain/builders/retriever_context.rb +25 -0
  11. data/lib/llm_chain/builders/tool_responses.rb +27 -0
  12. data/lib/llm_chain/chain.rb +89 -88
  13. data/lib/llm_chain/client_registry.rb +2 -0
  14. data/lib/llm_chain/clients/base.rb +24 -2
  15. data/lib/llm_chain/clients/deepseek_coder_v2.rb +32 -0
  16. data/lib/llm_chain/configuration_validator.rb +1 -1
  17. data/lib/llm_chain/interfaces/builders/memory_context_builder.rb +20 -0
  18. data/lib/llm_chain/interfaces/builders/prompt_builder.rb +23 -0
  19. data/lib/llm_chain/interfaces/builders/rag_documents_builder.rb +20 -0
  20. data/lib/llm_chain/interfaces/builders/retriever_context_builder.rb +22 -0
  21. data/lib/llm_chain/interfaces/builders/tool_responses_builder.rb +20 -0
  22. data/lib/llm_chain/interfaces/memory.rb +38 -0
  23. data/lib/llm_chain/interfaces/tool_manager.rb +87 -0
  24. data/lib/llm_chain/memory/array.rb +18 -1
  25. data/lib/llm_chain/memory/redis.rb +20 -3
  26. data/lib/llm_chain/system_diagnostics.rb +73 -0
  27. data/lib/llm_chain/tools/base.rb +103 -0
  28. data/lib/llm_chain/tools/base_tool.rb +6 -76
  29. data/lib/llm_chain/tools/calculator.rb +118 -45
  30. data/lib/llm_chain/tools/code_interpreter.rb +43 -43
  31. data/lib/llm_chain/tools/date_time.rb +58 -0
  32. data/lib/llm_chain/tools/tool_manager.rb +46 -88
  33. data/lib/llm_chain/tools/tool_manager_factory.rb +44 -0
  34. data/lib/llm_chain/tools/web_search.rb +168 -336
  35. data/lib/llm_chain/version.rb +1 -1
  36. data/lib/llm_chain.rb +58 -56
  37. metadata +19 -2
@@ -1,6 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../interfaces/tool_manager'
4
+
1
5
  module LLMChain
2
6
  module Tools
3
- class ToolManager
7
+ # ToolManager manages registration, selection, and execution of tools in LLMChain.
8
+ # Implements the LLMChain::Interfaces::ToolManager interface.
9
+ class ToolManager < Interfaces::ToolManager
4
10
  attr_reader :tools
5
11
 
6
12
  def initialize(tools: [])
@@ -8,43 +14,49 @@ module LLMChain
8
14
  tools.each { |tool| register_tool(tool) }
9
15
  end
10
16
 
11
- # Регистрирует новый инструмент
17
+ # Register a new tool instance.
18
+ # @param tool [LLMChain::Tools::Base]
19
+ # @return [void]
12
20
  def register_tool(tool)
13
- unless tool.is_a?(BaseTool)
14
- raise ArgumentError, "Tool must inherit from BaseTool"
21
+ unless tool.is_a?(Base)
22
+ raise ArgumentError, "Tool must inherit from LLMChain::Tools::Base"
15
23
  end
16
24
  @tools[tool.name] = tool
17
25
  end
18
26
 
19
- # Удаляет инструмент
27
+ # Unregister a tool by name.
28
+ # @param name [String]
29
+ # @return [void]
20
30
  def unregister_tool(name)
21
31
  @tools.delete(name.to_s)
22
32
  end
23
33
 
24
- # Получает инструмент по имени
34
+ # Fetch a tool by its name.
35
+ # @param name [String]
36
+ # @return [LLMChain::Tools::Base, nil]
25
37
  def get_tool(name)
26
38
  @tools[name.to_s]
27
39
  end
28
40
 
29
- # Возвращает список всех инструментов
41
+ # List all registered tools.
42
+ # @return [Array<LLMChain::Tools::Base>]
30
43
  def list_tools
31
44
  @tools.values
32
45
  end
33
46
 
34
- # Получает схемы всех инструментов для LLM
35
- def get_tools_schema
36
- @tools.values.map(&:to_schema)
37
- end
38
-
39
- # Находит подходящие инструменты для промпта
47
+ # Find tools whose #match? returns true for the prompt.
48
+ # @param prompt [String]
49
+ # @return [Array<LLMChain::Tools::Base>]
40
50
  def find_matching_tools(prompt)
41
51
  @tools.values.select { |tool| tool.match?(prompt) }
42
52
  end
43
53
 
44
- # Выполняет все подходящие инструменты
54
+ # Execute every matching tool and collect results.
55
+ # @param prompt [String]
56
+ # @param context [Hash]
57
+ # @return [Hash] mapping tool name → result hash
45
58
  def execute_tools(prompt, context: {})
46
59
  matching_tools = find_matching_tools(prompt)
47
-
48
60
  results = {}
49
61
  matching_tools.each do |tool|
50
62
  begin
@@ -62,102 +74,45 @@ module LLMChain
62
74
  }
63
75
  end
64
76
  end
65
-
66
77
  results
67
78
  end
68
79
 
69
- # Выполняет конкретный инструмент по имени
70
- def execute_tool(name, prompt, context: {})
71
- tool = get_tool(name)
72
- raise ArgumentError, "Tool '#{name}' not found" unless tool
73
-
74
- begin
75
- result = tool.call(prompt, context: context)
76
- {
77
- success: true,
78
- result: result,
79
- formatted: tool.format_result(result)
80
- }
81
- rescue => e
82
- {
83
- success: false,
84
- error: e.message,
85
- formatted: "Error in #{name}: #{e.message}"
86
- }
87
- end
88
- end
89
-
90
- # Создает стандартный набор инструментов
91
- def self.create_default_toolset
92
- tools = [
93
- Calculator.new,
94
- WebSearch.new,
95
- CodeInterpreter.new
96
- ]
97
-
98
- new(tools: tools)
99
- end
100
-
101
- # Создает набор инструментов из конфигурации
102
- def self.from_config(config)
103
- tools = []
104
-
105
- config.each do |tool_config|
106
- tool_class = tool_config[:class] || tool_config['class']
107
- tool_options = tool_config[:options] || tool_config['options'] || {}
108
-
109
- case tool_class.to_s.downcase
110
- when 'calculator'
111
- tools << Calculator.new
112
- when 'web_search', 'websearch'
113
- tools << WebSearch.new(**tool_options)
114
- when 'code_interpreter', 'codeinterpreter'
115
- tools << CodeInterpreter.new(**tool_options)
116
- else
117
- raise ArgumentError, "Unknown tool class: #{tool_class}"
118
- end
119
- end
120
-
121
- new(tools: tools)
122
- end
123
-
124
- # Форматирует результаты выполнения для включения в промпт
80
+ # Format tool execution results for inclusion into an LLM prompt.
81
+ # @param results [Hash]
82
+ # @return [String]
125
83
  def format_tool_results(results)
126
84
  return "" if results.empty?
127
-
128
85
  formatted_results = results.map do |tool_name, result|
129
86
  "#{tool_name}: #{result[:formatted]}"
130
87
  end
131
-
132
88
  "Tool Results:\n#{formatted_results.join("\n\n")}"
133
89
  end
134
90
 
135
- # Получает краткое описание доступных инструментов
91
+ # Human-readable list of available tools.
92
+ # @return [String]
136
93
  def tools_description
137
94
  descriptions = @tools.values.map do |tool|
138
95
  "- #{tool.name}: #{tool.description}"
139
96
  end
140
-
141
97
  "Available tools:\n#{descriptions.join("\n")}"
142
98
  end
143
99
 
144
- # Проверяет, содержит ли промпт запрос на использование инструментов
100
+ # Determine if prompt likely needs tool usage.
101
+ # @param prompt [String]
102
+ # @return [Boolean]
145
103
  def needs_tools?(prompt)
146
- # Проверяем явные запросы на использование инструментов
147
104
  return true if prompt.match?(/\b(use tool|call tool|execute|calculate|search|run code)\b/i)
148
-
149
- # Проверяем, есть ли подходящие инструменты
150
105
  find_matching_tools(prompt).any?
151
106
  end
152
107
 
153
- # Автоматически решает, какие инструменты использовать
108
+ # Auto-select and execute best tools for prompt.
109
+ # @param prompt [String]
110
+ # @param context [Hash]
111
+ # @return [Hash]
154
112
  def auto_execute(prompt, context: {})
155
113
  return {} unless needs_tools?(prompt)
156
-
157
- # Ограничиваем количество одновременно выполняемых инструментов
158
114
  matching_tools = find_matching_tools(prompt)
159
115
  selected_tools = select_best_tools(matching_tools, prompt)
160
-
161
116
  results = {}
162
117
  selected_tools.each do |tool|
163
118
  begin
@@ -175,15 +130,19 @@ module LLMChain
175
130
  }
176
131
  end
177
132
  end
178
-
179
133
  results
180
134
  end
181
135
 
136
+ # Build JSON schemas for all registered tools.
137
+ # @return [Array<Hash>]
138
+ def get_tools_schema
139
+ @tools.values.map(&:to_schema)
140
+ end
141
+
182
142
  private
183
143
 
184
- # Выбирает лучшие инструменты для выполнения (ограничение по количеству)
144
+ # Simple heuristic to rank matching tools.
185
145
  def select_best_tools(tools, prompt, limit: 3)
186
- # Простая логика приоритизации
187
146
  prioritized = tools.sort_by do |tool|
188
147
  case tool.name
189
148
  when 'calculator'
@@ -196,7 +155,6 @@ module LLMChain
196
155
  1
197
156
  end
198
157
  end
199
-
200
158
  prioritized.first(limit)
201
159
  end
202
160
  end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LLMChain
4
+ module Tools
5
+ # Factory for creating ToolManager instances with default or custom toolsets.
6
+ module ToolManagerFactory
7
+ # Create a ToolManager with the default set of tools.
8
+ # @return [ToolManager]
9
+ def self.create_default_toolset
10
+ tools = [
11
+ Calculator.new,
12
+ WebSearch.new,
13
+ CodeInterpreter.new,
14
+ DateTime.new
15
+ ]
16
+ ToolManager.new(tools: tools)
17
+ end
18
+
19
+ # Create a ToolManager from a config array.
20
+ # @param config [Array<Hash>] tool config hashes
21
+ # @return [ToolManager]
22
+ def self.from_config(config)
23
+ tools = []
24
+ config.each do |tool_config|
25
+ tool_class = tool_config[:class] || tool_config['class']
26
+ tool_options = tool_config[:options] || tool_config['options'] || {}
27
+ case tool_class.to_s.downcase
28
+ when 'calculator'
29
+ tools << Calculator.new
30
+ when 'web_search', 'websearch'
31
+ tools << WebSearch.new(**tool_options)
32
+ when 'code_interpreter', 'codeinterpreter'
33
+ tools << CodeInterpreter.new(**tool_options)
34
+ when 'date_time', 'datetime'
35
+ tools << DateTime.new
36
+ else
37
+ raise ArgumentError, "Unknown tool class: #{tool_class}"
38
+ end
39
+ end
40
+ ToolManager.new(tools: tools)
41
+ end
42
+ end
43
+ end
44
+ end